I’m very new at testing so please let me know if I am just going off in completely the wrong direction at any point. Having said that, assume I want to test the following function, foo.
int foo(int i) {
//Lots of code here
i = bar();
//Some more changes to i happen here, conditional on what bar returned
return i;
}
In this example, both foo and bar are functions written by myself and I have already tested bar.
Since the output of foo is conditional on the output of bar, I assume that in order to test foo, I need to create a mock of bar. In order to do that, and assuming that the definition of bar is kept inside a separate source file from foo, I could create a new source file, include that instead of the one where the actual definition of bar is found, and put a mock of bar in that file.
int bar(void) {
return HARD_CODED_VALUE;
}
However, there are 2 problems with this approach:
1) What happens if bar returns multiple values (such as an error code or an actual value) and I need to ensure that foo reacts correctly for each possibility? I can’t create multiple definitions for bar. One thought I did have was to create a static int in bar and then increment it every time bar gets called. Then I just have a conditional on this int, call bar multiple times and thus return multiple values. However, I am unsure whether introducing more complex logic into a mock function is good practice or if there is a better way to achieve this:
int bar(void) {
static int i = 0;
i++;
if(i == 1) {
return HARD_CODED_VALUE_1
}
else if(i == 2) {
return HARD_CODED_VALUE_2
}
else {
fprintf(stderr, "You called bar too many times\n");
exit(1);
}
}
2) What happens if bar is in the same source file as foo? I can’t redefine bar nor separate foo and bar without altering my source code which would be a real pain.
Well, there are a few ways around that problem.
You could use preprocessor hooks to swap out
bar()when aUNITTESTflag is set:You could simulate Dependency Injection, and require a pointer to
bar()as a parameter to the function. I’m not saying that’s a great idea in practice, but you could do it.I’m sure there are others, but that’s just 2 that came off the top of my head…