Mockito:@InjectMocks(OK)与模拟对象的构造函数(NPE)
Mockito: @InjectMocks (OK) vs constructor of mocked objects (NPE)
这里是应该测试的class:
public class UserService {
private final UserDAO userDAO;
private final TransactionManager transactionManager;
public UserService(UserDAO userDAO, TransactionManager transactionManager) {
this.userDAO = userDAO;
this.transactionManager = transactionManager;
}
public boolean isUserEmailUnique(HttpServletRequest req, Connection connection) {
User user = transactionManager //---- NPE if no InjectMocks was done -----
.doInTransaction(connection, (con) ->
userDAO.getUserByEmail(con, req.getParameter(Attributes.EMAIL)));
return Objects.isNull(user);
}
这里是测试class:
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
@Mock HttpServletRequest mockedReq;
@Mock TransactionManager mockedTransactionManager;
@Mock Connection mockedConnection;
UserService userService; // QUESTION IS ABOUT THAT OBJECT
@Test
public void ifSuchUserWasNotFound_ThenEmailIsUnique() {
doReturn(new User()).when(mockedTransactionManager).doInTransaction(any(Connection.class), any(TransactionOperation.class));
assertFalse(userService.isUserEmailUnique(mockedReq, mockedConnection));
doReturn(null).when(mockedTransactionManager).doInTransaction(any(Connection.class), any(TransactionOperation.class));
assertTrue(userService.isUserEmailUnique(mockedReq, mockedConnection));
}
如果我将模拟注入到被测试的 userService
中,如下所示,这个测试工作正常。
@InjectMocks UserService userService;
但是如果我创建一个新实例并将模拟对象传递给构造函数,如下所示,在测试的 class
中会抛出一个关于 transactionManager
的 NullPointerException
// no @InjectMocks
UserService userService = new UserService(mockedUserDAO, mockedTransactionManager);
这不应该是一回事吗?也许我是一个坏人 reader,但官方 article 并没有说 @InjectMocks
应该做一些特殊的事情,这对于基本构造函数是不可用的。
知道为什么传递给构造函数的模拟对象仍然为空吗?
按照事件顺序:
UserService userService = new UserService(mockedUserDAO, mockedTransactionManager);
创建实例作为创建测试 class 实例的一部分,但 mockito 尚未 运行 因此 mockedUserDAO
和 mockedTransactionManager
为空。
将实例创建移至设置方法:
UserService userService;
@Before
public void prepareTest() {
userService = new UserService(mockedUserDAO, mockedTransactionManager);
}
这里是应该测试的class:
public class UserService {
private final UserDAO userDAO;
private final TransactionManager transactionManager;
public UserService(UserDAO userDAO, TransactionManager transactionManager) {
this.userDAO = userDAO;
this.transactionManager = transactionManager;
}
public boolean isUserEmailUnique(HttpServletRequest req, Connection connection) {
User user = transactionManager //---- NPE if no InjectMocks was done -----
.doInTransaction(connection, (con) ->
userDAO.getUserByEmail(con, req.getParameter(Attributes.EMAIL)));
return Objects.isNull(user);
}
这里是测试class:
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
@Mock HttpServletRequest mockedReq;
@Mock TransactionManager mockedTransactionManager;
@Mock Connection mockedConnection;
UserService userService; // QUESTION IS ABOUT THAT OBJECT
@Test
public void ifSuchUserWasNotFound_ThenEmailIsUnique() {
doReturn(new User()).when(mockedTransactionManager).doInTransaction(any(Connection.class), any(TransactionOperation.class));
assertFalse(userService.isUserEmailUnique(mockedReq, mockedConnection));
doReturn(null).when(mockedTransactionManager).doInTransaction(any(Connection.class), any(TransactionOperation.class));
assertTrue(userService.isUserEmailUnique(mockedReq, mockedConnection));
}
如果我将模拟注入到被测试的 userService
中,如下所示,这个测试工作正常。
@InjectMocks UserService userService;
但是如果我创建一个新实例并将模拟对象传递给构造函数,如下所示,在测试的 class
中会抛出一个关于transactionManager
的 NullPointerException
// no @InjectMocks
UserService userService = new UserService(mockedUserDAO, mockedTransactionManager);
这不应该是一回事吗?也许我是一个坏人 reader,但官方 article 并没有说 @InjectMocks
应该做一些特殊的事情,这对于基本构造函数是不可用的。
知道为什么传递给构造函数的模拟对象仍然为空吗?
按照事件顺序:
UserService userService = new UserService(mockedUserDAO, mockedTransactionManager);
创建实例作为创建测试 class 实例的一部分,但 mockito 尚未 运行 因此 mockedUserDAO
和 mockedTransactionManager
为空。
将实例创建移至设置方法:
UserService userService;
@Before
public void prepareTest() {
userService = new UserService(mockedUserDAO, mockedTransactionManager);
}