Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Mockito detect mock usage and field assignments?

This use case is perhaps best explained by the test:

@Test
public void testZeroInteraction() {
    Pika pika = new Pika();
    Trainer trainer=mock(Trainer.class);

    pika.doNothing3(trainer);
    verifyZeroInteractions(trainer);
}

This is my doNothing3() method in class Pika:

void doNothing3(Trainer trainerIn){
    trainer=trainerIn;
    trainerIn.name="Ash";
}

In this case, verifyZeroInteractions() does not complain and the test passes.

Can Mockito detect assignments as those in the doNothing3 method above?

If so, what Mockito method can be used?

like image 238
DDC Avatar asked Sep 05 '25 03:09

DDC


1 Answers

OO is about behavior, not state.

Right the first paragraph in the Mockito documentation reads:

Let's verify some behaviour! ...

In that sense; when Mockito talks about interaction, what they (or any other mocking framework to my knowledge) mean is: method calls.

In other words: the mocked object knows nothing about the fields of the class it is mocking.

So, you could basically do the following:

  1. keep your current testZeroInteraction() test (to prove that no methods are called)
  2. add a second test, to check that a real input object doesn't change

Like:

@Test
public void testFieldUpdates() {
  Pika pika = new Pika();
  Trainer orig = new Trainer();  
  Trainer copy = new Trainer(orig);
  pika.doNothing3(copy);
  assertThat(orig, is(copy));

}

What this test "means": create a trainer object, and then create a copy of that. Pass the first object into your method; and afterwards check if that object still equals the copy.

But of course - that requires that you have some sort of "copy constructor"; and also a reasonable implementation of equals().

Finally: you should actually start by stepping back. My first sentence is: "OO is about behavior, not state". Translating to: the idea of having a Trainer class with public writeable fields is a design smell. You shouldn't do that. You don't create objects, pass them around and have other code directly write to fields. You call methods on other objects, you don't manipulate their state.

In other words: your approach violates a whole set of important OO principles. And because of that, Mockito is not supporting what you are doing. Because nobody should be doing what you are doing. So, as said: the real answer here is to fix your broken design.

like image 52
GhostCat Avatar answered Sep 07 '25 19:09

GhostCat