How would you create a mock object framework for a non-object oriented language? It’s not as weird as it sounds. There’s a lot of procedural code out there, and unless the world falls to ruin and the last C compiler gets all of its bits munged, there’s going to be a lot more in the future.
I was thinking about this recently and I had the realization that maybe this is a case where it makes sense to jump above the native language. Most mocking frameworks have you work in the language you’re developing in. You set expectations for various objects prior to calling methods which talk to them. Here’s an example from the JMock documentation:
final Subscriber subscriber = context.mock(Subscriber.class);
Publisher publisher = new Publisher();
publisher.add(subscriber);
final String message = "message";
context.checking(new Expectations() {{
one (subscriber).receive(message);
}});
publisher.publish(message);
In a language like C, however, there aren’t any objects to work with, unless you’re cobbling them together yourself with structs and function pointers.
What if there was a language which allowed you to create specifications for individual functions, like this:
function send_port_command with 90, “CMD: 12”
calls io_mode which returns M_READ
calls set_mode with M_WRITE
calls write_byte with 90
calls write_bytes with “12”
returns E_OKAY
You could use it to drive a function like this:
status send_port_command(byte port, const char *message)
{
if(io_mode() == M_READ)
set_mode(M_WRITE);
write_byte(port)
write_bytes(translate_command(message));
return E_OKAY;
}
This is part of a larger question, really. We’ve done a lot with testing frameworks over the years, but does the testing concern deserve its own standalone DSL? Not one built in a language, but rather a separate language?

Comments (5)
Do you mean something like DejaGNU?
Posted by Andre Bogus | December 4, 2007 2:37 PM
Interesting point. Theoretically speaking, I think you're right. Practically speaking however, I think that people use tend to use the facilities of their implementation language when writing their tests/specs.
Case-in-point: in your example code, you use M_READ, M_WRITE, and E_OKAY, which I'm assuming would be specified by the the C preprocessor. This is certainly more clear than writing the literal values, but it illustrates my point: it's hard (and undesirable?) to divorce how people specify successful code from the implementation environment of the code itself.
Posted by AndrewO | December 5, 2007 11:06 AM
Andre, does DejaGNU mock out function calls? I didn't see anything like that in the documentation.
Posted by Michael Feathers | December 5, 2007 3:30 PM
AndrewO, I think that a DSL like this could use an escape hatch where you can drop down and write code in the target language, and, in particular, declare data that you can use in the language.
I did the escape hatch trick a long time ago in a DSL I wrote before people called them DSLs. :-)
Posted by Michael Feathers | December 5, 2007 3:35 PM
Interesting post! I posted comments on my weblog:
http://www.hans-eric.com/2007/12/10/does-unit-testing-deserve-its-own-dsl/
Regards
Posted by Hans-Eric Grönlund | December 11, 2007 8:49 AM