此问题在此处已有答案:
Why is my class not calling my mocked methods in unit test?(1个答案)
23天前关闭。
我声称我的测试失败是因为我的被测试类没有看到mock。我的证据是:
- 在调试器中,我的对象有普通的java.sql.* 父对象,它们不是Mockito.* 的。
- 当我尝试单步执行DbSql之类的对象时,我看到的是实际的DbSql代码,而不是Mockito代码。
- 当我运行时,executeQuery()抛出了一个NullPointerException。
以下是我的测试类的部分内容:
// Test Class
// My mocks:
HostMessage mockHostMessage;
DbConnect mockDbConnect;
DbCache mockDbCache;
DbSql mockDbSql;
ResultSet mockResultSet;
@BeforeEach
void setUp()
{
mockHostMessage = Mockito.mock(HostMessage.class);
mockDbConnect = Mockito.mock(DbConnect.class);
mockDbCache = Mockito.mock(DbCache.class);
mockDbSql = Mockito.mock(DbSql.class);
mockResultSet = Mockito.mock(ResultSet.class);
}
@Test
void myTest() {
String errMsg = "something";
try {
doReturn(mockDbSql).when(mockDbCache).getDbSql(any(), anyString());
doReturn(mockResultSet).when(mockDbSql).executeQuery();
doReturn(false).when(mockResultSet).next();
(new CartonRoutingProcessor()).process(mockDbConnect, mockHostMessage);
} catch(Throwable t) {
if(t instanceof MockitoException) {
fail(t.getMessage());
} else if(t instanceof SqlException) {
Assertions.assertTrue(t.getMessage().contains(errMsg),
"Phrase not found in SqlException message: " + errMsg);
fail(t.getMessage());
} else {
fail(t.getMessage());
}
}
下面是我的CartonRoutingProcessor业务逻辑的一部分:
public boolean process(DbConnect conn, HostMessage msg) throws SQLException
{
try(DbCache dbc = new DbCache())
{
DbSql mySql = dbc.getDbSql(conn, String.format("select id from routes"));
// Throws NullPointerException right here,
// while trying to execute the query rather than mock it.
ResultSet rs = mySql.executeQuery();
String routeType = rs.next() ? rs.getString("id") : null;
...
}
...
}
Mockito手册和大量的网页都讲述了如何执行此任务。
然而我没有得到我应该得到的结果。
一个善良的开发者能给我一个提示吗?
1条答案
按热度按时间fnx2tebb1#
这里您使用的是真实的实现而不是模拟
因此,在特定的测试场景中,您的模拟不会被使用。
当我看到一个mock返回一个mock返回一个mock时(等等,你明白了),我开始觉得要么代码是不可测试的,要么我的测试方法是糟糕的。毕竟,你想在这里测试什么?
假设您希望验证调用层响应
process
方法的true/false结果的行为。在这种情况下,可以模拟/监视整个process
,并人工创建响应,以便您可以专注于特定功能-响应结果另一方面,您可能希望测试
process
方法实际上是如何工作的,以及是否正确地获取了路由类型-但您应该使用actualtDB(例如,可以在内存中,如H2)来验证您是否正确地与DB交互,或者您可以在另一个将被监视的方法中进行整个获取。正确的方法取决于测试的实际目标及其范围(单元测试的范围非常窄-测试例如单一方法)。
在您的情况下,由于不是所有的“片段”都可以从外部提供(在这种情况下是模拟),我将坚持使用内存中的数据库-要做的存根较少。缺点是,现在您必须在数据库中准备实际数据,以便设置场景,这可能会很麻烦。