Delphi has had Unit Testing support (in the form of DUnit) for many years, but until now there very little in the way of Automatic Mocking. By contrast the .NET and Java worlds have plenty of mocking frameworks to choose from.
So what are Automatic Mocks anyway? Simply put, they are mock objects that you don't have to hand code. What's wrong with hand coding mock objects you might ask? Well nothing, really, but consider the following example, where we pass an
instance of our hand coded mock object to the object under test.
type IFoo = interface
function Bar(param : integer) : string;
end;
procedure TTestSomething.SimpleTest;
var
something : ISomething;
mockFoo : IFoo;
begin
something := TSomething.Create;
mockFoo := TMockFoo.Create;
something.UseFoo(mockFoo);
end;
What does our mockFoo mock object actually do, what is it's behavior, how many times will Bar be called and what will it return? It's not obvious from looking at the above code, so you would have to go off and find the TMockFoo
implementation. Not so hard, but what happens when someone else comes along and adds a new unit test that also uses TMockFoo, what happens if they change the TMockFoo implementation, will that break your existing tests. This is where automatic
mocks can help, because you define the behavior and expectations on you mock object right there in the unit test method :
procedure TTestSomething.SimpleTest;
var
something : ISomething;
mockFoo : TMock
begin
something := TSomething.Create;
//create our auto mock
mockFoo := TMock.Create;
//define the behavior of IFoo.Bar
mockFoo.Setup.WillReturn('hello something').When.Bar(1);
//define our expectations of how many times TSomething will call IFoo.Bar
mockFoo.Setup.Expect.Once.When.Bar(1);
//now lets test ISomething.UseFoo
something.UseFoo(mockFoo);
//Now verify that ISomething used IFoo correctly
mockFoo.Verify;
end;
The auto mock object is defined right there in our unit test, and the behavior is not going to change unless we change it in our unit test. This sort of mocking makes it simple to focus our testing effort on TSomething rather than TFoo
(our real IFoo implementation) or TMockFoo.
One of the reasons auto mocking hasn't really happened for Delphi is the lack of detailed and easy to use runtime type information (Rtti) and the lack of runtime code generation (yes it's always been possible, but not through a well
defined interface like Reflection.Emit in .NET). Auto mocking involves creating types on the fly, in the case of interfaces, creating a type and implementing an interface. That's not an easy thing to do. There are some examples of this in
Delphi's SOAP code, but they are not easy to follow. Delphi XE2 introduces some new features in the RTTI that make creating interface proxies simple. TVirtualInterface creates an implementation of an interface at runtime and marshals the method
calls to the OnInvoke method.
Delphi-Mocks - https://github.com/VSoftTechnologies/Delphi-Mocks is an attempt to create an Auto
Mocking framework for Delphi. It makes use of Generics and Fluent style interfaces. Currently only interfaces can be mocked, and it supports only Delphi XE2 at this time. I hope to add support for TObject mocks and earlier versions (D2009+).