|
|
@@ -0,0 +1,126 @@ |
|
|
|
# bdd-for-c-mocks |
|
|
|
|
|
|
|
## Usage |
|
|
|
|
|
|
|
Suppose you have a library `lib` and an application `app` that uses `lib`. You want to test `app` and you want to mock |
|
|
|
`lib`'s functions. You can do this by creating a mock header file for `lib` and including it in `app`'s test file. |
|
|
|
|
|
|
|
### `lib.h` |
|
|
|
|
|
|
|
This is a reference header file for `lib`. The implementation should be abstracted from us, and we want to be able to |
|
|
|
mock its behavior. |
|
|
|
|
|
|
|
```c |
|
|
|
#ifndef LIB_H |
|
|
|
#define LIB_H |
|
|
|
|
|
|
|
int add(int a, int b); |
|
|
|
|
|
|
|
void alert(); |
|
|
|
|
|
|
|
#endif |
|
|
|
``` |
|
|
|
|
|
|
|
### `lib.mock.h` |
|
|
|
|
|
|
|
We define mocked behavior for `lib`. `bdd-for-c-mocks` offers a capability to force mock behavior through modes. Note |
|
|
|
that all mode behaviors should be implemented already. |
|
|
|
|
|
|
|
```c |
|
|
|
#ifndef LIB_MOCK_H |
|
|
|
#define LIB_MOCK_H |
|
|
|
|
|
|
|
#include <bdd-for-c-mocks.h> |
|
|
|
|
|
|
|
mock_modes(add) { |
|
|
|
ADD_RETURNS_SUM = 0, |
|
|
|
ADD_RETURNS_CONSTANT_VALUE, |
|
|
|
}; |
|
|
|
|
|
|
|
mock(add) int add(int a, int b) { |
|
|
|
mock_mode_if(add, ADD_RETURNS_SUM) { |
|
|
|
// suppose we want to test normal behavior |
|
|
|
mock_return(add) a + b; |
|
|
|
} else mock_mode_if(add, ADD_RETURNS_CONSTANT_VALUE) { |
|
|
|
// maybe an edge case? |
|
|
|
mock_return(add) 5; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
mock(alert) void alert() { |
|
|
|
mock_return(alert); |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
``` |
|
|
|
|
|
|
|
### `app.h` |
|
|
|
```c |
|
|
|
#ifndef APP_H |
|
|
|
#define APP_H |
|
|
|
|
|
|
|
void math(); |
|
|
|
|
|
|
|
#endif |
|
|
|
``` |
|
|
|
|
|
|
|
### `app.c` |
|
|
|
|
|
|
|
This is a reference implementation of `app`. We want to test the invocations done inside the `math()` function. |
|
|
|
|
|
|
|
```c |
|
|
|
#include "lib.h" |
|
|
|
#include "app.h" |
|
|
|
|
|
|
|
void math() { |
|
|
|
int result_a = add(1, 2); |
|
|
|
int result_b = add(3, 4); |
|
|
|
if (result_a == result_b) { |
|
|
|
// this is the edge case! |
|
|
|
// alert() should be called if the add values are the same |
|
|
|
alert(); |
|
|
|
} |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
### `app.test.c` |
|
|
|
|
|
|
|
This is the test file for `app`. It includes `lib.mock.h` instead of `lib.c`. `lib.h` should still be linked because we |
|
|
|
are sharing the original function declarations. |
|
|
|
|
|
|
|
```c |
|
|
|
#include <bdd-for-c.h> |
|
|
|
#include "app.h" |
|
|
|
|
|
|
|
spec("app") { |
|
|
|
describe("math") { |
|
|
|
after_each() { |
|
|
|
mock_reset(add); |
|
|
|
} |
|
|
|
|
|
|
|
after_each() { |
|
|
|
mock_reset(alert); |
|
|
|
} |
|
|
|
|
|
|
|
it("calls add") { |
|
|
|
mock_mode(add, ADD_RETURNS_SUM); |
|
|
|
mock_set_excepted_calls(math, 2); |
|
|
|
|
|
|
|
math(); |
|
|
|
|
|
|
|
check( |
|
|
|
mock_get_expected_calls(math) == mock_get_actual_calls(math), |
|
|
|
"add was not called." |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
it("calls alert when calls from add return the same values") { |
|
|
|
mock_mode(add, ADD_RETURNS_CONSTANT_VALUE); |
|
|
|
|
|
|
|
math(); |
|
|
|
check(mock_is_called(alert), "alert was not called."); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
``` |