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?
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;
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.
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.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With