Wumba
Wumba

Reputation: 107

Does @InjectMock only inject mocks in global variables of a class?

I try to do the following test:

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 and injected
    @Mock
    private SomeDao someDao;

    @InjectMocks
    private SomeClass someClass = new someClass();

    @Test
    void test() {
       when(someDao.retrieveSomeData).thenReturn(10);
    }
}

This the simplified class where the object I want to inject is instantiated and used in a method:

public class SomeClass {
   private void someMethod() {
      SomeDao someDao = new SomeDao();
      someDao.retrievSomeData();
   }
}

But I can also write the class as following with the instantiation in the constructor:

public class SomeClass{
   SomeDao someDao;

   public SomeClass() {
      someDao = new SomeDao();
   }

   private void someMethod() {
      someDao.retrievSomeData();
  }
}

Result: It is still the real function with the reals object someDao.rerieveSomeData() called and not my mocked object! Why? I am rather confused.

Upvotes: 1

Views: 2306

Answers (1)

EricSchaefer
EricSchaefer

Reputation: 26370

@InjectMock can inject mocks in three ways:

  1. Constructor injection: If your SomeClass has a constructor parameter of type SomeDao it will pass the mock as that parameter.
  2. Setter injection: If SomeClass has a single setter method with a parameter of type SomeDao (e.g. setDao(SomeDao dao) or there are several such setters, but one has the same name as the mock (i.e. setSomeDao(SomeDao someDao)), it will call this setter with the mock as the parameter.
  3. Field injection: If there is a single field of type SomeDao or there are several fields of type SomeDao, but one field has the same name as your mock (i.e. someDao), it will set this field with the mock.

For your code this means you should never create an instance of SomeDao in your SomeClass class, but instead inject it. In your normal business code you would create the DAO outside of SomeClass and pass it to the constructor (which is usually the prefered injection variant). In your test mockito would then take care to do the same, but with the mock instead of the real DAO.

Upvotes: 1

Related Questions