5

When building a unit test, is it appropriate to use a mocking tool to assist you in setting up an object even if you will not be mocking any behavior or verifying any interaction with that object?

Here is a simple example in pseudo-code:

//an object we actually want to mock
Object someMockedObject = new Mock(Object.class);
EqualityChecker checker = new EqualityChecker(someMockedObject);

//an object we are stubbing/mocking only to avoid figuring out how to instantiate or 
//tying ourselves to some constructor that may be removed in the future
ComplicatedObject someObjectThatIsHardToInstantiate = new Mock(ComplicatedObject.class);

//set the expectation on the mock
When(someMockedObject).equals(someObjectThatIsHardToInstantiate).return(false);
Assert(equalityChecker.check(someObjectThatIsHardToInstantiate)).isFalse();

//verify that the mock was interacted with properly
Verify(someMockedObject).equals(someObjectThatIsHardToInstantiate).oneTime();

Is it appropriate to mock ComplicatedObject in this scenario?

smp7d
  • 4,221
  • 1
  • 24
  • 40
  • 1
    If it works, it works, but IMO, this would be an abuse of a mocking tool and may lead to maintenance issues down the line. – BrandonV Apr 17 '14 at 20:22
  • That's a fair test. You're validating the behavior of EqualityChecker & don't care what Object or ComplicatedObject do. Verify(someMockedObject) is redundant, because that interaction would have to be there for the test to pass. – sea-rob Apr 17 '14 at 21:04

3 Answers3

3

You don't really want a mock object. You want a stub. Basically you want a dumb object that takes the place of something complex so you can control that complex process without needing to validate that it works.

Mocks Aren't Stubs (Martin Fowler)

  • When I read that article (which I found interesting and well worth my time), I thought it seemed to say that, yes, the OP wants a stub, but that it was ok to use your mock framework, if it is easier then creating the stub yourself. – Guy Schalnat Jul 24 '14 at 02:06
  • Mocks aren't stubs, but most mocking frameworks provide an easy way to create a mock that is essentially a stub. – Kat Aug 02 '14 at 03:08
  • The example does not stub any behavior either. – smp7d Apr 14 '15 at 15:57
  • @smp7d: Correct. The OP's example does not stub any behavior, therefore you want a stub. It's all about how the object is intended to be used within the test. – Greg Burghardt Apr 14 '15 at 19:49
1

With Mockito, I would use the any() matcher.

When(someMockedObject).equals(any(ComplicatedObject.class)).return(false);

There might be something similar in your mocking framework.

Mike Partridge
  • 6,647
  • 1
  • 25
  • 39
  • I want it to match the instance specifically. If I use any the functionality could swap in an entirely different instance and the test would still pass. – smp7d Apr 14 '15 at 15:58
0

If "you will not be mocking any behavior or verifying any interaction with that object", it sounds like you will not be using that object at all in the unit under test, for that test. Can you just set the reference to null for that test? This makes it very clear that this dependency is irrelevant in this test.

If that is not possible, and you require it to be non-null, it means in fact you are expecting some interaction with it. If your use case really shouldnt be interacting with it at all, it kind of seems like the code under test has a design issue.

jordan
  • 501
  • The problem with this is that then the code under test has to be littered with these little null checks everywhere for depedencies that you are forcing to be injected in your constructor. I prefer to provide "null-object" instances that behave as expected. – Matt Klinker Jun 02 '14 at 20:20