0

I am using JUnit5.

I have following scenario:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;


@ExtendWith(MockitoExtension.class)
public class SomeClassTest {

    // needs to be mocked but not injected
    @Mock
    private EntityManager entityManager;
    
    // needs to be mocked and injected
    @Mock
    private SomeDao someDao;

    @InjectMocks
    private SomeClass someClass = new someClass(entityManager);

public class SomeClass{

   EntityManager entityManager;

   public SomeClass(EntityManager entityManager) {
      if (entityManager == null) {
         throw new NullpointerException("Manager is null");
      } else {
         this.entityManager = entityManager;
}

The problem is:

  • mocked EntityManager object is needed to create the class I want to test
  • must inject SomeDao which is needed in SomeClass
  • I get a nullpointer because the mocked object appears not to be created when I give it as argument to the constructor

Has anybody an idea how to solve this? I could create a no-arg constructor but that would give me a constructor which I only need for testing which isn't that 'clean'.

Wumba
  • 99
  • 1
  • 12
  • 1. Drop `new someClass(entityManager)` initialization. 2. Add somedao as constructor argument. – Lesiak Apr 09 '21 at 17:12

2 Answers2

2

You should add your SomeDao someDao as an arg to SomeClass constructor and then you will be able to manipulate it via tests using @Mock

nesmeyana
  • 186
  • 1
  • 1
  • 5
0

Looking at this answer (https://stackoverflow.com/a/67081911/11431537) Mockito is using 3 ways to inject a mock. The first one is injecting it in the constructor if there is a constructor which takes the argument.

Therefore, I changed my constructor as @nesmeyana mentioned:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import javax.persistence.EntityManager;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;


@ExtendWith(MockitoExtension.class)
public class SomeClassTest {

    @Mock
    private EntityManager mockEntityManager;

    @Mock
    private SomeDao mockSomeDao;

    @InjectMocks
    private SomeClass someClass;

    @Test
    public void test() {
        when(mockSomeDao.duck()).thenReturn(10);

        assertEquals(10, someClass.bla());
    }
}
public class SomeClass{

   EntityManager entityManager;
   
   SomeDao someDao;


   public SomeClass(EntityManager entityManager, SomeDao someDao) {
      if (entityManager == null) {
         throw new NullpointerException("Manager is null");
      } else {
         this.entityManager = entityManager;

      this.someDao = someDao;
}
public class SomeDao{
    int x = 5;

    public SomeDao(int x) {
        this.x = x;
    }

    public int duck() {
        return x;
    }
}

But since I had to change my code to be able to test my classes, I have to rethink my code writing in general! I and everybody who reads this, should avoid hard dependencies and use CI (dependency injection) to be able to test their code easily.

Wumba
  • 99
  • 1
  • 12