USQ91
USQ91

Reputation: 352

Mocking a JPA repository with Mockito in Java does not get invoked

I'm writing unit tests for a Service Implementation that uses JPA repo - MessageRepository, which returns a "Wanted but not invoked: Actually, there were zero interactions with this mock" when I try to verify if it's being invoked. I've extracted parts of code to simplify problem explanation.

Service Implementation:

public class MessageServiceImpl {

  private final MessageRepository messageRepository;

  public MessageServiceImpl(MessageRepository messageRepository) {
    this.messageRepository = messageRepository;
  }

  public Message create(){
    Message result;        
    //some operations...
    Message message = new Message();
    message.setId(2L);
    message.setName("123231231");
    ...

    result = save(message);
    return  result;
  }

  public Message save(Message message){
    Message result = messageRepository.save(message); // returns a null when I debug while Testing
    return result;
  }

}

Unit Test Class

@RunWith(SpringRunner.class)
public class MessageServiceImplUnitTest {

@Mock
MessageRepository messageRepository;

@Mock
OtherService otherService; // not a jpa repo but uses one in its implementation and works just as expected

@InjectMocks
MessageServiceImpl messageService;

Message message;

@Before
public void setup() {

    initMocks(this);
    message = new Message();
    message.setId(1L);
    message.setMessageDirection(MessageDirection.OUT);
}


// Unit Test for create method of MessageServiceImpl which should return a non-null Message Obj
@Test
public void createShouldReturnNotNullMessageObj(){

    // mocking save method to return the same Obj that was passed
    when(messageRepository.save(any(Message.class))).then(AdditionalAnswers.returnsFirstArg());

    Message result = messageService.create(); 

    // This fails and displays "Wanted but not invoked: Actually, there were 
    // zero interactions with this mock" 
    verify(messageRepository).save(any(Message.class));

    Assert.assertNotNull(result);
}

I can't figure out why other mock services are working as expected but the repository does not get invoked. As a result, the Message Obj is returned as null from save(Message message) obj.

Upvotes: 0

Views: 4366

Answers (2)

JB Nizet
JB Nizet

Reputation: 691715

Remove @SpringBootTest(classes = Abc.class): it's a unit test, not an integration test.

Remove @Autowired: you're using constructor injection.

Remove messageService = new MessageServiceImpl(messageRepository);: the Mockito annotations do that for you, and since you have initMocks() after this instruction, messageRepository is still null at that point anyway.

Remove RunWith(MockitoJUnitRunner.class)since you're calling initMocks() explicitly in your code.

Upvotes: 1

Thihara
Thihara

Reputation: 6969

You are using @InjectMocks on your messageService variable. And the initialize it on the constructor itself.

Do one of those, not both, my guess is that's where your problem lies. The @InjectMock initializes your object and inject the mocks in for you. If you do that and initialize your object manually, results can be unpredictable.

Your wiring is also off, you are using constructor initialization but has the @Autowired annotation on the field, move it to the constructor.

You also have SpringBootTest annotation on top of your class, which is not necessary for a unit test.

Upvotes: 0

Related Questions