A simple C mock

1,139 views
Skip to first unread message

Michal Dubovský

unread,
Oct 26, 2017, 8:19:43 AM10/26/17
to cpputest
Hello, I am struggling with the basic mocking workflow for C functions.
I am using CPP testing interface.
Les's say I have my source application source.c that I am testing and I want to test Foo():

int Bar(void)
{
 return MY_SCARY_DEPENDENCY;
}

int Foo(void)
{
  return Bar();
}

Now I want the Foo() to be independent of Bar() so I would like to create a Bar() mock that just returns (for example) number 5 if it is called from withing the Foo() function. Could you please help and specify what to write in my unit_test.cpp test file and in source.c in order to accomplish this?

James W Grenning

unread,
Oct 26, 2017, 8:35:23 AM10/26/17
to cpputest

Hello Michal

Are those functions in the same file? If so you need Bar to be a function pointer so you can override it.

Or, but Bar in its own C file and you can use the linker to override it.

James

--
You received this message because you are subscribed to the Google Groups "cpputest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cpputest+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Michal Dubovský

unread,
Oct 26, 2017, 9:07:33 AM10/26/17
to cpputest
Thank you for the quick reply!

The Bar() is in the same folder.

Can you please provide an example?

Michal Dubovský

unread,
Oct 26, 2017, 9:29:42 AM10/26/17
to cpputest
Sorry, I meant it is in the same file.

James W Grenning

unread,
Oct 26, 2017, 10:13:22 AM10/26/17
to cpputest

From your question, you must be very new to C. Here is a stack overflow on function pointers. You should be able to figure it out from this.

https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work

in an h file:

extern int (*Bar)(void);

In the C file:

static int bar(void)
{
    // the real implementation
}

int (*Bar)(void) = bar;

In the test file:

Thank you for the quick reply!

The Bar() is in the same folder.

Can you please provide an example?


-- 

Michal Dubovský

unread,
Oct 26, 2017, 12:02:53 PM10/26/17
to cpputest
I know how to use function pointers. I use them quiet regulary. 
The think I don't know is how to use the testing framework.
The "In the test file:" part of your reply is missing, that is the most critical part for me.

Thanks again for the help. I appreciate it ;)

Michal Dubovský

unread,
Oct 26, 2017, 12:12:36 PM10/26/17
to cpputest
Oh, and very crucial thing by the way. Bar() is indeed static so I am including a "*.c" source file in my test file so that the Bar() is in the scope of a test file and can be tested separately as well.

Michal Dubovský

unread,
Oct 27, 2017, 3:44:59 AM10/27/17
to cpputest
I am going to elaborate a bit. I have tried creating a function pointer and here is the result:

In my .h file:
extern int (*myDependency)(void);
int MyPublicFunction(int param1);


In my .c file:
static int myDependency_impl(void)
{
 
return 5;
}


int (*myDependency)(void) = &myDependency_impl;


int MyPublicFunction(int param1)
{
 
return myDependency();
}


In my test file:
extern "C"
{
#include "..\my_header.h"
}


#include "CppUTest/TestHarness.h"
#include "CppUtestExt/MockSupport.h"


TEST_GROUP
(MockTest)
{
 
void setup() {}
 
void teardown()
 
{
 mock
("MyMock").clear();
 
}
};


int myDependency_test(void)
{
 
return mock("MyMock")
 
.actualCall("myDependency")
 
.returnValue().getIntValue();
}


TEST
(MockTest, FirstMockTest)
{
 mock
("MyMock")
 
.expectOneCall("myDependency")
 
.andReturnValue(10);


 
int (*myDependency)(void) = &myDependency_test;
 
int retval = MyPublicFunction(0);


 mock
("MyMock")
 
.checkExpectations();
}


Now I expect the MyPublicFunction()to be called and myDependency_test() to be called from within the body of MyPublicFunction().
But instead I get this compilation error:
unresolved external symbol _MyPublicFunction referenced in function "public: virtual void __thiscall TEST_MockTest_FirstMockTest_Test::testBody(void)" (?testBody@TEST_MockTest_FirstMockTest_Test@@UAEXXZ)

Bas Vodde

unread,
Oct 27, 2017, 3:56:26 AM10/27/17
to CppUTest

Hi Michal,

I copy-pasted your code in files and was able to compile it. The test failed.

I think the problem isn’t in the code but how you compile it. Could you tell me what compiler commands or makefile you use?

Thanks!

Bas

Michal Dubovský

unread,
Oct 27, 2017, 4:44:44 AM10/27/17
to cpputest
I use Visual Studio 2017.

Just to be sure I did not mess up any setup I tried the original VS project:
  1. Git-cloned the cpputest repository
  2. Opened the VS project
  3. Build
  4. Run
  5. Some ~1100 tests ran OK, everything as expected
  6. I deleted all of the old tests and wrote couple of simple ones myself (no mocks used)
  7. Build & Run
  8. Still everything OK, tests run as intended
  9. I try to use my mock code that is listed above
  10. Still the same error

Bas Vodde

unread,
Oct 27, 2017, 4:48:51 AM10/27/17
to cppu...@googlegroups.com

Hi,

Strange. The problem doesn’t seem to be with the code. I can’t replicate it as I use no Windows.

Uhm, did you link the CppUTestExt library? That might be it…

Thanks,

Bas

Michal Dubovský

unread,
Oct 27, 2017, 5:21:09 AM10/27/17
to cpputest
CppUTest and CppUTestExt are both compiled in one library CppUTestd.lib and it is indeed linked.

Dňa piatok, 27. októbra 2017 10:48:51 UTC+2 Bas Vodde napísal(-a):

Bas Vodde

unread,
Oct 27, 2017, 6:48:43 AM10/27/17
to cppu...@googlegroups.com

Ok. Strange.

Then I’m not clear why you get the linker error, but it seems to be build related as it compiled well locally.

I’ll attach the files.

Thanks,

Bas

heh.c
heh.h
main.cpp
test.cpp

Michal Dubovský

unread,
Oct 27, 2017, 9:44:55 AM10/27/17
to cpputest
Ok, I got it. The .c source file that was being tested needed to be added into the workspace of visual studio (even though it was in a folder that was added to include directiories).
Everything seems to work now. Thank you guys for the help. 
By the way James I saw a recording of your presentation in Norway - very helpful as well.

Michal Dubovský

unread,
Oct 27, 2017, 10:35:33 AM10/27/17
to cpputest
I don't want to start another thread so I'll just continue here.
I have tested all of my "public" functions in a way that static functions were just mocks.
Now how do I test the static functions? If I include the *.c file so they are in the scope I get errors that _Foo() is already defined in xyz.obj.
I suppose this could be solved by adding some kind of wrapper function or testing the static functions in another project, or is there a better approach?
And more importantly. What if there is a static function that is dependent on another static function? Like:

static int FooImpl(void)
{
 
return 5;
}
void (*Foo)(void) = &FooImpl;

static int BarImpl(void)
{
 
return Foo();
}
void (*Bar)(void) = &BarImpl;

How would I test BarImpl() in isolation from the FooImpl()?

Bas Vodde

unread,
Oct 28, 2017, 8:32:20 AM10/28/17
to cppu...@googlegroups.com
Hi Michal,

Uhm, by changing the function pointer Foo to an empty function?

I'm not quite sure I understand the question as the answer seems too obvious?

Thanks!

Bas

James W Grenning

unread,
Oct 28, 2017, 9:38:32 AM10/28/17
to cpputest

No worries. Sorry for my assumption.

--
You received this message because you are subscribed to the Google Groups "cpputest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cpputest+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

James W Grenning

unread,
Oct 28, 2017, 9:40:22 AM10/28/17
to cpputest

What recording was that?

--
You received this message because you are subscribed to the Google Groups "cpputest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cpputest+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

James W Grenning

unread,
Oct 28, 2017, 9:50:47 AM10/28/17
to cpputest

You have access to the statics through the function pointer.

Generally -- testing static functions

If a static cannot be tested through the compilation unit's public interface, you have a design problem.

Having to include the .c in a test is a good legacy code test technique, but it tells you the compilation unit has too much stuff in it.

--
You received this message because you are subscribed to the Google Groups "cpputest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cpputest+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Michal Dubovský

unread,
Oct 30, 2017, 4:04:59 AM10/30/17
to cpputest
James: This one - https://vimeo.com/131194135

You have access to the statics through the function pointer.

 Ok, let's imagine a scenario where I have one static and one public function that I want to test
static int FooImpl(void)
{
 
return 5;
}
void (*Foo)(void) = &FooImpl;

int Bar(void)
{
  // Do stuff dependent on Foo()
  return return_value;
}

Now I would have two tests, one to test the Bar() where Foo function pointer would be changed to my mock and the other test would test FooImpl() but there is no way to call it as the Foo function pointer was already changed to my mock and scope of FooImpl is limited to the *.c file it is located in. Is there any other way to call the FooImpl() than to create a public function that returns a pointer to it?

Because to write every static function like this seems like too much work (and also makes code a bit less readable):
C file:
static int FooImpl(void)
{
 
return 5;
}
void (*Foo)(void) = &FooImpl;

FOO_P FooImpl_p(void)
{
  return &FooImpl;
}

H file:
typedef int (*FOO_P)(void);
FOO_P FooImpl_p(void);


Steven Collins

unread,
Oct 30, 2017, 6:10:02 AM10/30/17
to cppu...@googlegroups.com
You need to expose foo in the header file, not fooImpl_p.  You need to be able to manipulate the pointer during tests. You could add a setter in addition to the getter, but to me that just seems like a lot of extra noise. Good tests should undo any test-exclusive changes they make. i.e.;


TEST_GROUP(Bar) {
  FOO_P savedFoo;

  setup() {
    savedFoo = foo;
    foo = testFoo;
  }

  teardown() {
    foo = savedFoo;
  }
};


TEST_GROUP(fooImpl) {
};


I'm assuming you know how to write testFoo. Now your tests for Bar get their test version of the function while you use the unmodified function pointer in the Foo group to test the fooImpl. Note that your foo pointer should be declared returning int, not void.


--
You received this message because you are subscribed to the Google Groups "cpputest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cpputest+unsubscribe@googlegroups.com.

Michal Dubovský

unread,
Oct 30, 2017, 6:37:40 AM10/30/17
to cpputest
Note that your foo pointer should be declared returning int, not void.

Typo, my bad.

FOO_P savedFoo;

Brilliant, elegant, works like a charm. Thank you ;) 
Reply all
Reply to author
Forward
0 new messages