Skip to content

Mocking: Stdout/stderr interception

Example: share/doc/aceunit/examples/hello_world_intercepted_obj

This approach doesn’t mock puts() at all. Only main is renamed with objcopy, same as the other object-based strategies:

Terminal window
objcopy --redefine-sym main=original_main hello.o mocked_hello.o

An Interceptor helper (interceptor.c) redirects both stdout and stderr through pipes: for each stream it dup()s the original file descriptor, opens a pipe, and dup2()s the pipe’s write end over the stream. After original_main() runs, it restores the original file descriptor and reads back whatever was written to the pipe on each stream:

void test_hello(void) {
Interceptor *interceptor = Interceptor_start();
int exitStatus = original_main();
char stdoutBuffer[4096];
char stderrBuffer[4096];
Interceptor_stop(&interceptor, stdoutBuffer, sizeof(stdoutBuffer), stderrBuffer, sizeof(stderrBuffer));
assert(0 == exitStatus);
assertStrEquals("Hello, world!\n", stdoutBuffer);
assertStrEquals("", stderrBuffer);
}

This verifies the real puts() call end-to-end — both what it wrote and that it wrote nothing to stderr — rather than replacing it with a mock.

Use this when you’d rather assert on real output than introduce a mock/fake for a function as simple as puts. It avoids the extra moving part of a mock implementation, at the cost of testing through an actual pipe/OS interaction rather than an in-process fake.

See also: objcopy override, which mocks puts directly instead of capturing real output.