Mock objects framework...?

Christopher Wright dhasenan at gmail.com
Tue Nov 6 07:03:26 PST 2007


Robert Fraser wrote:
> Christopher Wright Wrote:
> 
>> It will likely not have support for multiple mock repositories or even 
>> multiple mocks of the same type. It will likely not have support for 
>> mocked objects of one type and real objects of the same type. Not unless 
>> I rewrite everything as a giant string mixin. Which would probably turn 
>> out better.
>>
>> Keep bothering me, and it'll get done.
> 
> From my (limited) experience with D metaprogramming, I've found giant string mixins/CTFE functions are more flexible and scalable than templates, at the loss of some readability.

Now that I'm using giant string mixins and inheritance rather than code 
mixins and delegates and redirection, I have some progress. Using 
inheritance means we have, for the forseeable future:
	Multiple mocks of the same type.
	Mocks and real objects of the same type.
	No final or static methods.
	No fields.

And currently, all we can do is register calls and match them later. No 
return value setting, currently. No ignoring arguments. No putting in a 
delegate to execute or check anything. But I can do those relatively 
quickly.

I'm planning on using a fluent interface like the one in Rhino Mocks. 
(I've also used jMocks, but since it's in Java and uses anonymous 
classes, it's really weird, and I can't really translate it to D that 
well.) If you have any suggestions or examples of how you want things to 
look, let me know. The default (if nobody objects or comes up with a 
better idea) will be:

class IWillBeMockingThis {
	int foo () { return 0; }
	void bar (int i) { /* do stuff */ }
	void dontCallMe (int i, uint j) {}
}

unittest {
	MockRepository repository = new MockRepository();
	auto m = repository.Mock!(IWillBeMockingThis);
	Expect(m.foo).Return(31).Repeat(0, 5);

	/* The following might be useful, but it's low priority. */
	Expect(m.bar).Arguments(12);
	Expect(m.bar(-1));
	m.foo;
	repository.LastCall.Return(3);

	bool called = false;
	m.bar(1241);
	repository.LastCall.Arguments.Any()
		  .Do((int i) { called = true; });

	repository.ReplayAll();

	/* do stuff */

	m.dontCallMe(-3, 12); /* throws an exception */
	
	repository.VerifyAll(); /* throws an exception for each call that has 
been expected and wasn't called, subject to Repeat. */
}

This all has not been implemented yet. But the stuff to create a mock 
object with an arbitrary payload on each method is there.

Given how annoying it will likely be to instantiate a mock repository 
each test and how much extra typing it could be, I'll probably provide a 
mock test fixture class with convenience methods for creating mocks and 
accessing the last call and so forth.

I've requested space on dsource.org; I'm hesitant to do anything more 
until I have a revision control system at my hands.



More information about the Digitalmars-d mailing list