Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting mocks with Mockito does not work

I'm using Mockito to test my Spring project, but the @InjectMocks seems not working in injecting a mocked service into another Spring service(bean).

Here is my Spring service that I want to test:

@Service
public class CreateMailboxService {   
    @Autowired UserInfoService mUserInfoService; // this should be mocked
    @Autowired LogicService mLogicService;  // this should be autowired by Spring

    public void createMailbox() {
        // do mething
        System.out.println("test 2: " + mUserInfoService.getData());
    }

}

And below is the service that I want to mock:

@Service
public class UserInfoService {
    public String getData() {
        return "original text";
    }
}

My test code is here:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class CreateMailboxServiceMockTest {

    @Mock
    UserInfoService mUserInfoService;

    @InjectMocks
    @Autowired
    CreateMailboxService mCreateMailboxService;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void deleteWithPermission() {
        when(mUserInfoService.getData()).thenReturn("mocked text");
    
        System.out.println("test 1: " + mUserInfoService.getData());
    
        mCreateMailboxService.createMailbox();
    }
}

but the result would like

test 1: mocked text
test 2: original text  // I want this be "mocked text", too

it seems that the CreateMailboxService didn't get the mocked UserInfoService but using Spring's autowired bean. Why is my @InjectMocks not working?

like image 376
Victor Tsai Avatar asked Jan 11 '17 06:01

Victor Tsai


4 Answers

In my case, I had a similar issue when I worked with JUnit5

@ExtendWith(MockitoExtension.class)
class MyServiceTest {
...

@InjectMocks
MyService underTest;

@Test
void myMethodTest() {
...
}

underTest was null. The cause of the problem was that I used @Test from JUnit4 package import org.junit.Test; instead JUnit5 import org.junit.jupiter.api.Test;

like image 183
Oleg Ushakov Avatar answered Oct 24 '22 08:10

Oleg Ushakov


For those who stumbles on this thread and are running with JUnit 5 you need to replace @RunWith(SpringJUnit4ClassRunner.class)

with

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)

Further reading here. Unfortunately there is no hint when executing the test cases with JUnit 5 using the old annotation.

like image 31
Andreas Avatar answered Oct 24 '22 08:10

Andreas


You can create package level setter for mUserInfoService in CreateMailboxService class.

@Service
public class CreateMailboxService {   
    @Autowired UserInfoService mUserInfoService; // this should be mocked
    @Autowired LogicService mLogicService;  // this should be autowired by Spring

    public void createMailbox() {
        // do mething
        System.out.println("test 2: " + mUserInfoService.getData());
    }

    void setUserInfoService(UserInfoService mUserInfoService) {
        this.mUserInfoService = mUserInfoService;
    }
}

Then, you can inject that mock in the test using the setter.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class CreateMailboxServiceMockTest {

    @Mock
    UserInfoService mUserInfoService;

    CreateMailboxService mCreateMailboxService;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mCreateMailboxService = new CreateMailboxService();
        mCreateMailboxService.setUserInfoService(mUserInfoService);
    }

    ...
}

This way you can avoid problems with @InjectMocks and Spring annotations.

like image 8
alayor Avatar answered Oct 24 '22 09:10

alayor


If you are trying to use the @Mock annotation for a test that relies directly on Spring injection, you may need to replace @Mock with @MockBean @Inject (both annotations), and @InjectMocks with @Inject. Using your example:

@MockBean
@Inject
UserInfoService mUserInfoService;

@Inject
CreateMailboxService mCreateMailboxService;
like image 5
Derek Nash Avatar answered Oct 24 '22 10:10

Derek Nash