With many software developers now embracing test driven development, unit testing has become a regular practice. Unit testing, however, has a few obstacles. One of those obstacles is how to avoid dependencies and achieve isolation so that your unit tests are not actually integration testsómocking comes to the rescue!

History of Mocking

[caption id="" align="alignright" width="227" caption="Rails has 3 environments: production, development and test. The test environment is maintained in order to isolate testing changes from both production and development areas."]RailsEnvironments[/caption]

In the short history of mocking, there has been quite a progression. The first mocks were real classes with fake data input. This was to avoid having to run through all of your data and save time during testing. This was accomplished by creating a testing database or by creating a general testing environment. This is still used today in integration testing and can be seen in the Rails framework.

But, that was difficult. Developers would have to create and maintain a large supporting structure for their codebase. Changes in development environments would need to be made to test environments, as well. The mental load of testing also increased: developers would need to know the entire dataflow of their application in order to perform testing. There needed to be a better way.

[caption id="" align="alignleft" width="159" caption="An example of "Mock classing" where a developer creates a class specifically for mocking behavior of a superclass and break dependencies."]MockClasses[/caption]

Some developers started creating ways to separate logical parts of the code. They did this by creating ìMockî classes that were subclasses of the classes in between logical sections of code. For example, Class B is the class that we are attempting to test. Class B uses Class A (and A is injected) to talk to the Database.† So, as a good unit tester, we create a test class for B called BTest. However, in order to test some functions of B, A is required. We really donít want to talk to the database for a variety of reasons[1]. These developers would create a subclass of A called ìAMockî that would break the communication between A and the database. Then, BTest could inject AMock into B for testing purposes only.

This was a Good Thing(TM). It made testing easier and now developers didnít have to maintain separate environments. As a tradeoff, the developers did need to maintain an entire mocking library that subclassed their own API. In addition, it made tests look weird. They went from this

A dependency = new A()
dependency.setDatabaseName("Test")
dependency.setDatabaseActive()
B target = new B(dependency)
B.someFunction()

to this

A dependency = new AMock()
B target = new B(dependency)
B.someFunction()

which looks like the developer is testing something entirely different. That was a small price to pay for the isolation that was provided.

But, there were developments in the dynamic language world. People were looking at the above structure and saying ìWell, I donít really need to subclass since my language is dynamic. Instead, I could create a generic mock.î Thus, the modern day mock was born. In Ruby, libraries like FlexMock and Mocha started to appear. Shortly after, mocking libraries like Moq and NMock in static languages popped up. Now, every language seems to have a mock library. These libraries are clever little tools that help the developers test their code. But how do they work?

Modern Mocking Libraries

Modern mocks operate under the assumption that there should be one mock class that mocks everything. You can literally throw anything into these mocks and theyíll break dependencies and create isolation for unit tests. Cool. How?

[caption id="" align="alignright" width="429" caption="An example of how mock libraries might work in a dynamic language. The mock libraries intercept the runtime's call to the method table and handle it in a special way."]DynamicMock[/caption]

In most cases, a mock is just a ìwrapperî or an ìadapterî around your object. However, instead of adapting to a specific set of APIs and redirecting them as needed, a mock will intercept all requests to the underlying object. It is best explained using dynamic languages (static languages have different ways of implementing this and they are far more complication). When you make a call to an object, that object goes and finds its method and, using the method signature, marshals the call to the appropriate function. Letís call that function on all of our objects ìfindMethod.î

So, when we want to find ìBarî method on ìFoo,î we can just ask the methodTable for it with the ìfindMethodî call. Itíll return the method in question and the runtime can go about its business. But, with mocks, we want to intercept that call. So we wrap the Foo object with some Mock object that will now be the recipient of those calls from the runtime. The Mock can override the findMethod call and check to see if the Foo class has the method ìBarî with ìhasMethod.î If Foo has a method called Bar, we can return a dummy object. If Foo doesnít have a method called Bar, we can throw an exception. And, this is the case for any instance of Foo, any method on Foo, and any class in this dynamic language. Wow. With one override we seemed to have eliminated all dependency issues that could ever arise in unit testing.

Of course, mocking libraries have diversified and gone on to create new advancements. Most libraries, for example, implement expectations. Expectations allow for developers to test that dependencies are being used correctly in their class. Some libraries allow for calls to be ìpassed throughî in order to maintain some dependencies. Some allow for setting of return values or of throwing exceptions on a method call. The feature list grows every day and each feature is a great tool to creating more effective tests.

OJMoq

OJMoq is a Mock library that I wrote for Objective-J. OJMoq is inspired by Moq, a mocking library for .NET. It implements several of the features of a modern mocking library. It is also very lightweight. It is easy to use and understand.

Making use of OJMoq in Cappuccino

OJMoq was created so that I could effectively write unit tests in Cappuccino. In particular, we are going to have a complex model and controller architecture that requires some good dependency management. So, Iím going to demonstrate some good practices when coding tests in Cappuccino.

Models are the domain of the application and should always have dependencies injected. Here is an example:

 @implementation OJUser : CPObject
    ...
    - (void)initWithConnection:(OJConnection)connection
    ...
    - (void)save
    {
        [connection save:self];
    }

Now, I don't care what connection does when "save" is called. All I care about is that save is called and that I'm passing it the correct object. So, to test this, the following test would be created:

 - (void)testThatUserSendsSaveToConnectionOnSave
    {
        var connection = moq([[OJConnection alloc] init]);
        var target = [[OJUser alloc] initWithConnection:connection];

        [connection expectThatSelector:@selector(save:) isCalled:1 withArguments:[CPArray arrayWithObject:target]];

        [target save];

        [connection verifyThatAllExpectationsHaveBeenMet];
    }

And, now, we have a very effective test that would be ugly and hard to read (and, perhaps, not worth our time) otherwise. Now, in order to test controllers, we have a similar setup:

 @implementation OJUserController : CPObject
    ...
    - (void)initWithViewRepository:(OJViewRepository)repository withContentView:(CPView)contentView
    ...
    - (void)userWantsUserList
    {
        // remove currentView
        [contentView addSubview:[repository userListView]];
    }

If you are familiar with trying to test this sort of controller in ojtest, you know that is impossible. Views interact with the browser and in ojtest there doesn't exist a browser. So any normal test would fail. But, we can actually test this with mocks!

 - (void)testThatContentViewAddsUserListViewWhenUserWantsUserList
    {
        var viewRepository = moq([[OJViewRepository alloc] init]);
        var contentView = moq([[CPView alloc] initWithFrame:CGRectMakeZero()]);
        var userListView = [[CPObject alloc] init]; // I don't care what this is! As long as it is set as a subview.
        var target = [[OJUserController alloc] initWithViewRepository:viewRepository withContentView:contentView];

        [viewRepository selector:@selector(userListView) returns:userListView];
        [contentView expectThatSelector:@selector(addSubview:) isCalled:1 withArguments:[CPArray arrayWithObject:userListView]];

        [target userWantsUserList];

        [viewRepository verifyThatAllExpectationsHaveBeenMet];
        [contentView verifyThatAllExpectationsHaveBeenMet];
    }

And, now, you have a test that verifies the exact behavior of your controller. Mocking allows for developers to quickly and efficiently check the behavior of their code. It makes almost any kind of test possible, as long as dependencies are managed correctly.

Go to GitHub to find out more about OJMoq.