如何模拟由 MyBatis 初始化的接口引用?
How to mock an interface's reference which is initialized by MyBatis?
在标记此 Answer 的副本之前,请理解该答案无法解决我的问题。答案给出了我在当前方法中使用 when()
的解决方案。在我的问题中,UserDao
正在初始化,否则无法传递被测方法内部和模拟对象。
有一个接口的引用是MyBatis初始化的。我不能在测试中直接模拟它,因为该对象没有传递到测试的主题中。我必须通过模拟构造函数来 PowerMock 它。因为没有调用接口的构造函数,PowerMock 抛出异常。
java.lang.ArrayIndexOutOfBoundsException: 0
at org.powermock.api.mockito.internal.expectation.AbstractConstructorExpectationSetup.withAnyArguments(AbstractConstructorExpectationSetup.java:100)
这是代码的样子
class UserServiceTest{
@AutoWired
UserService userService;
@Mock
UserDao userDao;//This is a reference to the interface (UserDao) which is mapped using MyBatis
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
//The Program fails at the below statement
PowerMockito.whenNew(UserDao.class).withAnyArguments().thenReturn(userDao);
@Test
public void testFetchDetails() throws Exception {
when(userDao.fetchDetails(any(ParameterOne.class)).thenReturn(null);
assertThat(userService.fetchDetails(new ParameterOne())).isNull();
}
}
如果我 运行 没有 PowerMock 的程序,实际的数据库被访问并且 returns 正确的结果。访问数据库还会导致测试速度减慢 运行 时间增加到 500 毫秒。
如何模拟 UserDao userDao
?如果我不能模拟在这种情况下如何执行单元测试。我无法更改正在测试的代码。
P.S。如果您仍然建议我避免使用 PowerMock,请在这种情况下提出 "better" 替代方案。
P.P.S 请注意,我不是在测试 Dao 层,而是在测试使用 Dao 层的服务,因此,我必须模拟 DaoLayer 来检查服务的行为是否正确。
该应用程序是 spring-引导应用程序。我将 @InjectMocks
用于测试中的 class,将 @Mock
用于任何需要模拟的对象。
@RunWith(SpringRunner.class)
class UserServiceTest{
@InjectMocks
UserService userService;
@Mock
UserDao userDao;//This is a reference to the interface (UserDao) which is mapped using MyBatis
...
}
这有效,我可以直接在模拟对象上使用 when()/given()。
在标记此 Answer 的副本之前,请理解该答案无法解决我的问题。答案给出了我在当前方法中使用 when()
的解决方案。在我的问题中,UserDao
正在初始化,否则无法传递被测方法内部和模拟对象。
有一个接口的引用是MyBatis初始化的。我不能在测试中直接模拟它,因为该对象没有传递到测试的主题中。我必须通过模拟构造函数来 PowerMock 它。因为没有调用接口的构造函数,PowerMock 抛出异常。
java.lang.ArrayIndexOutOfBoundsException: 0
at org.powermock.api.mockito.internal.expectation.AbstractConstructorExpectationSetup.withAnyArguments(AbstractConstructorExpectationSetup.java:100)
这是代码的样子
class UserServiceTest{
@AutoWired
UserService userService;
@Mock
UserDao userDao;//This is a reference to the interface (UserDao) which is mapped using MyBatis
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
//The Program fails at the below statement
PowerMockito.whenNew(UserDao.class).withAnyArguments().thenReturn(userDao);
@Test
public void testFetchDetails() throws Exception {
when(userDao.fetchDetails(any(ParameterOne.class)).thenReturn(null);
assertThat(userService.fetchDetails(new ParameterOne())).isNull();
}
}
如果我 运行 没有 PowerMock 的程序,实际的数据库被访问并且 returns 正确的结果。访问数据库还会导致测试速度减慢 运行 时间增加到 500 毫秒。
如何模拟 UserDao userDao
?如果我不能模拟在这种情况下如何执行单元测试。我无法更改正在测试的代码。
P.S。如果您仍然建议我避免使用 PowerMock,请在这种情况下提出 "better" 替代方案。
P.P.S 请注意,我不是在测试 Dao 层,而是在测试使用 Dao 层的服务,因此,我必须模拟 DaoLayer 来检查服务的行为是否正确。
该应用程序是 spring-引导应用程序。我将 @InjectMocks
用于测试中的 class,将 @Mock
用于任何需要模拟的对象。
@RunWith(SpringRunner.class)
class UserServiceTest{
@InjectMocks
UserService userService;
@Mock
UserDao userDao;//This is a reference to the interface (UserDao) which is mapped using MyBatis
...
}
这有效,我可以直接在模拟对象上使用 when()/given()。