subclass-and-override vs partial mocking vs refactoring

Attention all noble mockers and evil partial mockers. Actually… both styles are evil :) Spy, don’t mock… or better: do whatever you like just keep writing beautiful, clean and non-brittle tests.

Let’s get to the point: partial mocking smelled funny to me for a long time. I thought I didn’t need because frankly, I haven’t found a situation where I could use it.

Until few days ago when I found a place for it. Did I just come to terms with partial mocks? Maybe. Interestingly, partial mock scenario seems to be related with working with code that we don’t have full control of…

I’ve been hacking a new feature for mockito, an experiment which suppose to enhance the feedback from a failing test. On the way, I encountered a spot where partial mocking appeared handy. I decided to code the problem in few different ways and convince myself that partial mocking is a true blessing.

Here is an implementation of a JunitRunner. I trimmed it a little bit so that only interesting stuff stayed. The runner should print warnings only when the test fails. The super.run(notifier) is wrapped in a separate method so that I can replace this method from the test:

initial-code1

How would the test look like? I’m going to subclass-and-override to replace runTestBody() behavior. This will give me opportunity to test the run() method.

subclass-and-override1

It’s ugly but shhh… let’s blame the jUnit API.

The runTestBody() method is quite naughty but I’ve got a powerful weapon at hand: partial mocking. What’s that? Typically mocking consist of using a replacement of the entire object. Partial stands for replacing only the part of real implementation, for example a single method.

Here is the test, using hypothetical Mockito partial mocking syntax. Actually, shouldn’t I call it partial stubbing?

partial-mocking1

Both tests are quite similar. I test MockitoJUnitRunner class by replacing the implementation of runTestBody(notifier). First example uses test specific implementation of the class under test. Second test uses a kind of partial mocking. This sort of comparison was very nicely done in this blog post by Phil Haack. I guess I came to the similar conclusion and I believe that:

  • subclass-and-override is not worse than partial mocking
  • subclass-and-override might give cleaner code just like in my example. It all depends on the case at hand, though. I’m sure there are scenarios where partial mocking looks & reads neater.

Hold on a sec! What about refactoring? Some say that instead of partial mocking we should design the code better. Let’s see.

The code might look like this. There is a specific interface JunitTestBody that I can inject from the test. And yes, I know I’m quite bad at naming types.

refactored-code1

Now, I can inject a proper mock or an anonymous implementation of entire JunitTestBody interface. I’m not concerned about the injection style because I don’t feel it matters that much here. I’m passing JunitTestBody as an argument.

refactored-test

Let’s draw some conclusions. In this particular scenario choosing refactoring over partial mocking doesn’t really push me towards the better design. I don’t want to get into details but junit API constrains me a bit here so I cannot refactor that freely. Obviously, you can figure out a better refactoring – I’m just yet another java developer. On the other hand, the partial mocking scenario is a very rare finding for me. I believe there might be something wrong in my code if I had to partial mock too often. After all, look at the tests above – can you say they are beautiful? I can’t.

So,

  • I cannot say subclass-and-override < partial mocking
  • not always refactoring > subclass-and-override/partial mocking
  • partial mocking might be helpful but I’d rather not overuse it.
  • partial mocking scenario seems to lurk in situations where I cannot refactor that freely.

Eventually, I chose subclass-and-override for my implementation. It’s simple, reads nicer and feels less mocky & more natural.

Advertisement

9 Responses to subclass-and-override vs partial mocking vs refactoring

  1. [...] Mockito author’s last blog post about the subject or this mockito mailing list post. Basically the code should be refactored or we [...]

  2. [...] is mostly by-design decision on Mockity side. The author argues that partial mocking smells fishy, and that it’s better to refactor the code and eliminates [...]

  3. Alexander Kjeldaas says:

    This spy(…) syntax doesn’t work if the class you’re testing is abstract and takes a constructor argument.

    In that case you can’t create an object for the spy syntax, so I think there’s something wrong/lacking with the Mockito API for this. There needs to be a way to inject dependencies into an abstract class.

  4. szczepiq says:

    actually, it should be possible to spy on abstract classes. Don’t remember now but it will be something like that : mock(Foo.class, withSettings()…

  5. Anonymous says:

    I have stubbed mocked class in my test class but I am not getting the expected return.
    will you please tell me Why?

  6. szczepiq says:

    Ping the mailing list with the sample code and the community should give some help. Cheers!

  7. Anonymous says:

    when( dynamicRecommendationsManager.getNextAction(bankCustomer,
    otherServiceToCust, borrowingLimits, address, custNeed, questionReply)).thenReturn(nba)

    in the above code otherServiceToCust and questionReply are list and all others are objects returned from other services which have been stubbed.

    I think the problem is with list. is there any way to send NonNull list in stubbing as we do in jMockery framework

  8. Anonymous says:

    i am new to mockito. which mailing list you are talking about

Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.