For another easier pattern, like the one in the Mockito home page:
TInterfaceMock.Create(TypeInfo(ICalculator),ICalc,self).
ExpectsCount('Multiply',qoEqualTo,1).
ExpectsCount('Add',[10,20],qoEqualTo,1);
ICalc.Add(10,20);
ICalc.Multiply(10,30)
If you want to follow the "test spy" pattern, you can use:
Mock := TInterfaceMockSpy.Create(TypeInfo(ICalculator),ICalc,self);
ICalc.Add(10,20);
ICalc.Multiply(10,30)
Mock.Verify('Add');
Mock.Verify('Multiply',[10,30]);
If you compare with existing mocking frameworks, even in other languages / platforms like the two above, you will find out that the features included in mORMot are quite complete:
- Stubbing of any method, returning default values for results;
- Definition of the stubbed behavior via a simple fluent interface, with
TInterfaceStub.Returns(), including easy definition of returned results values, for the whole method or following parameters/arguments matchers; - Handle methods with
var, outor function result returned values - i.e. not only the function result (as other Delphi implementations does, due to a limitation of theTVirtualInterfacestandard implementation, on which mORMot does not rely), but all outgoing values, as an array of values; - Stubbed methods can use delegates or event callbacks with
TInterfaceStub.Executes()rule definitions, for the whole method or following parameters/arguments matchers, to run a more complex process; - Stubbed methods can also raise exceptions with
TInterfaceStub.Raises()rule definitions, for the whole method or following parameters/arguments matchers, if this is the behavior to be tested; - Clear distinction between
mocks and stubs, with two dedicated classes, named
TInterfaceStubandTInterfaceMock; - Mocks are directly linked to mORMot's unitary tests / test-driven classes;
- Mocked methods can trigger test case failure with
TInterfaceMock.Fails()definitions, for the whole method or following parameters/arguments matchers; - Mocking via "expect-run-verify" or "run-verify" (aka "test spy") patterns, on choice, depending on your testing expectations;
- Mocking validation against number of execution of a method, or a method
with arguments/parameters matchers, or the global execution trace - in this
case, pass count can be compared with operators like
< <= = <> > >=and not only the classic exact-number-of-times and at-least-once verification; - Most common parameters and results definitions can be defined as simple
array of constin the Delphi code, or by supplying JSON arrays (needed e.g. for more complex structures likerecordvalues); - Execution trace retrieval in easy to read or write text format (and not via
complex "fluent" interface e.g. with
Whenclauses); - Auto-release of the
TInterfaceStub TInterfaceMock TInterfaceMockSpygenerator instance, when the interface is no longer required, to minimize the code to type, and avoid potential memory leaks; - Works from Delphi 6 up to XE3 - since no use of syntax sugar like generics,
nor the
RTTI.pasfeatures; - Very good performance (the faster Delphi mocking framework, for sure), due
to very low overhead and its reuse of mORMot's low-level
interface-based services kernel using JSON serialization, which does not rely
on the slow and limited
TVirtualInterface.
This article is part of a list of mocking/stubbing range of information:
- Interfaces in practice: dependency injection, stubs and mocks
- Stubs and Mocks for Delphi with mORMot;
- Advanced mocks and stubs;
Feedback is welcome on our forum, just as usual.

