Mock Shmock

There have been several posts in past week regarding testing, basically trying to explain, that as with anything in software development, things should be taken and applied cautiously. One of the most horrible things that can be done to a software project is using mocks in the wrong way. Let me try and explain why:

Do we really need it?

First, lets start with why do we want to use mocks. On any given project, if someone tells me that they want to test a service implementation (assuming that it performs some dao calls, and some business logic) and mocking out the dao, I would ask them several times if it is really needed. At the end of the day, the most important part of the service layer is to expose a service API, and we would want to test this service API without knowing what is going on within it. It means, that our integration tests, and what I mean by integration here is an environment that works with other immediate external dependencies, like database or other frameworks/libraries, will have to be written in order to prove that our service layer is functional. You can not and should not rely only on your mock tests for it. Now, if we already have the integration tests, which have 100% coverage of all the different execution paths of the service, why would we want to complicate our code with mock tests?

Many of you would then say that integration tests are slow, and mock tests are fast. But I say that if you are running your integration tests against an in memory HSQL instances, and rollback each transaction, it is fast enough.

Another issue that people raise is the fact that if the test fails, we won’t know immediately what went wrong. It might be our test data, transaction handling, or any other non business related aspect of the services tests. What people miss is that most of the time, this is not the case, and the problem is pretty evident. And let me remind you that you still need to run your integration tests, so you would need to solve this problem anyhow.

Test Code is part of your source code

Tests, let it be unit/integration/orwhatchamacolo tests, are part of your source code. When you refactor your main code base, you might need to refactor your test code base as well. Mock tests for the most part are intrusive in nature, they know things about how certain services are executed, how they are called, and the order of their internal execution plan. This means that when you refactor your code, you will need to spend time refactoring your mock tests as well, many times without the IDE help.

From my experience, refactoring mock tests is a pain. Many times you extend the functionality of your service, without changing its API contract, and suddenly mock tests start dropping like flies. This is very noticeble when testing services.

The Danger Of Mocks

Like most things in software development, certain tools / methodologies can be very dangerous in the hands of people who abuse them. Writing proper mock testing is not simple, as well as the decision what to mock test and what not. On several projects that I have worked on, mocks were used as the golden hammer of testing. The projects had so many mock tests, many of them with such an obscure execution and coding, that trying to change existing functionality required changing so many tests. Suddenly a 1 hour feature became a full day work.

The strange thing was that the developers on the project were all above average developers, which for me means that doing proper mock testing, without it being a hassle later on in the porject life is not a simple job, and requires a lot of decipline.

This brings me back to my first point, we still had to write integration tests (and run them before any commit). This integration tests retested most of the mock tests, and we ended up with test duplication, which should be treated as bad as code duplication.

Last Words

I am not saying that mock tests should not be used. I am simply saying that we need to be vigilant in applying it within our code base. There are places where it makes perfect sense to write mocks, and they should be used in such cases. Also, many times, simple mock implementation of an interface (sometimes called stub) is simpler then using an existing mock library, and requires much less understanding or the knowledge of yet another library we use in our project.

4 Responses to “Mock Shmock”

  1. Andres Almiray Says:

    Shay, you are correct that if having 100% coverage on integration tests you don’t need mock tests BUT having 100% coverage in integration is too late.

    I assure you’ll never get to the 100% mark on integration with ease (I think is not even possible if you follow the traditional approach instead of TDD), because you have to test limits (done with unit testing), paths (also with unit + mock) and whatever approach you need; you’ll never get out of that swamp!

    Probably you have seen the advantages of mocking advertised somewhere, but for me, the ability to test a component right away when using DC (Design by Contract) without having to wait for the its dependencies to be finished by my teammates is something I’ll never want to loose.

    Besides unit testing with mocks when designed and coded properly serve as a starting point for integration testing, just change configuration and replace mocks for real components (I see your point of code duplication).

    Finally, I agree that a simpler custom Stub can do the job, so far JMock has covered all my needs and not a single custom Stub has been necessary (your milage may vary).

    Whatever option you take, keep on testing!

  2. Twice Says:

    I agree with design by contract point made above and that’s where i found mocks really valuable.

  3. Vitali Chkliar Says:

    I absolutely agree with you Shay. For the last project I used JWebUnit, hibernate with caching, and ActiveTestSuite to run independent tests in parallel. My JWebUnit tests were enough for specifications and test. All tests run under 20 seconds. The worse thing in having too many tests is refactoring.

  4. Sabarish Sasidharan Says:

    +1

    I too don’t think thorough mock testing is necessary. Integration tests, that assume the code to be a blackbox, have worked for me consistently. I do resort to individual unit tests (though not using mocks) when i have to test complex logic (which is quite rare).

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>