Question

I have written quite a few Mock objects using EasyMock. However, often i find writing partial mocks time consuming, and it does not feel 'right'.

I'd say its a design fault as my class I try to mock has multiple concerns into one, therefore I should create seperate classes in order to seperate concerns.

What do you think? Is partially mocking a good or bad thing? And, if good/bad, why? What would you suggest if you notice you cannot mock the object because you only want to mock a few methods?

Was it helpful?

Solution

If you find yourself creating partial mocks on a regular basis, it might be a sign that too much state and functionality is being thrown into a small number of classes. This can make your code more difficult to maintain and reason about and consequently harder to unit test. It can also lead to code duplication or circular dependencies if you find out later that some other component in your system needs a subset of the functionality contained in one of your large classes.

Try to identify related groups of functionality and break those out into smaller helper classes that can be unit tested independently. This will make the code easier to understand, enables you to write finer-grained unit tests, and you may find opportunities to reuse the functionality you've split out in different contexts sometime in the future. If you're using a dependency injection framework like Spring or Guice, it will be easy to wire those objects back together when your application runs.

Figuring out the best way to refactor large classes is something one learns through experience. Generally, though, I try to look at what a class is doing and give names to the different roles it plays at different points in processing. Then I create new classes for those roles. For example, if I had a class that reads through a server log file and emails an administrator when certain entries are found there, I might refactor that into one class that knows how to parse log files, a second class that looks for the trigger entries, and a third that knows how to notify administrators. The trick is to limit how much "knowledge" is contained in each class. This also gives you the opportunity to abstract out general concepts. For example, by breaking your classes up this way, you could support different notification mechanisms or kinds of trigger conditions in the future without impacting your log parsing class or its unit test.

OTHER TIPS

I personally am not a fan of partial mocks because it means that your test of ClassA then depends in some part on the behavior of ClassB - and the point of mocking is to be able to test ClassA independent of any implementation details of any of it's colloborators.

I'm confused on what you mean by "you only want to mock a few methods". What version of EasyMock are you using? Typically you only need to supply expectations and return values for the methods that will actually be called. Or do you mean that you are writing stub versions of these classes?

If you are concerned that your colloborator "has multiple concerns into one", you could always try to break up it's interface into several different interfaces - and the implementation class can just implement all of them. This way, you can supply different mocks in your unit test (one per interface), even if your implementation is still just a single class.

My opinion is: partial mocking is fine, especially when you:

• mock methods that call JNI methods, e.g.

public void methodToTest() {
    int result = invokeLibraryCode();
}

// This method will be mocked
int invokeLibraryCode() {
    // This method is native:
    com.3rdparty.Library.invokeMethod(); 
}

• mock methods that operate with current date, while you need to control the date:

public void methodToTest() {
    Calendar cal = getCurrentDate();
}

// This method will be mocked
Calendar getCurrentDate() {
    return Calendar.getInstance();
}

• mock InputStream, Process and other abstract classes:

public void methodToTest(InputStream is) throws IOException {
    int i = is.read(); // is.read() is mocked
}

You can of course, cover first two cases with an interface (wrap com.3rdparty.Library into your own interface, implement CurrentDateProvider, etc but I think that is overcomplicating things).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top