JMockit 没有在 Expectations 块中实例化捕获的接口
JMockit is not instantiating captured interfaces in Expectations block
我不确定是我没有正确使用 JMockit,还是我的设置有问题。我在 Eclipse 中使用 JMockit 1.32 和 JUnit 4.12。
我的问题似乎是没有捕获接口。具体在 java.sql
包中。例如:
public class Dto {
private int id;
public Dto(){}
public Dto(ResultSet rs) {
try {
id = rs.getInt(1);
} catch (SQLException e) { }
}
public int getId() {return id;}
void setId(int id) {this.id = id;}
}
.
public class ClassUnderTest {
public static Dto loadObject(Connection conn, String tablename, int id) {
Dto result = null;
ResultSet rs = null;
PreparedStatement ps = null;
try {
String sql = "select * from " + tablename + " where id = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
rs = ps.executeQuery();
if (rs.next()) {
result = new Dto(rs);
}
} catch (SQLException e) {
} finally {
try {
if (ps != null) ps.close();
} catch (SQLException e) { }
}
return result;
}
}
.
public class ResultSetTest extends junit.framework.TestCase {
private static final int OBJ_ID = 5;
@Capturing
ResultSet mockResultSet;
@Capturing
PreparedStatement mockStatement;
@Capturing
Connection mockConn;
@Test
public void testGetDtoById() throws SQLException {
new Expectations() {{
mockConn.prepareStatement(anyString); result = mockStatement;
mockStatement.setInt(anyInt, OBJ_ID);
mockResultSet.next(); result = true;
new Dto(mockResultSet); result = new Dto();
mockResultSet.next(); result = true;
}};
Dto dto = ClassUnderTest.loadObject(mockConn, "", OBJ_ID);
assertEquals(dto.getId(), OBJ_ID);
}
}
在此设置中,测试执行失败并在 Expectations(){}
块的第一行出现 NPE。但是从教程等来看,我希望创建一个模拟实例。 (e.g. tutorial)
为了克服这个问题,我创建了显式模拟 类,如下所示:
public class ResultSetMockup extends MockUp<ResultSet> { }
public class PreparedStatementMockup extends MockUp<PreparedStatement>
{
@Mock ResultSet executeQuery() {return new ResultSetMockup().getMockInstance();}
}
public class ConnectionMockup extends MockUp<Connection>
{
@Mock PreparedStatement prepareStatement(String sql) throws SQLException {
return new PreparedStatementMockup().getMockInstance();
}
}
@Capturing
ResultSet mockResultSet = new ResultSetMockup().getMockInstance();
@Capturing
PreparedStatement mockStatement = new PreparedStatementMockup().getMockInstance();
@Capturing
Connection mockConn = new ConnectionMockup().getMockInstance();
在这一点上,Expectations() {}
块是快乐的,但似乎从未真正设置 results
。通过设置断点,我看到 rs.next()
总是失败。所以我认为实际上没有捕获任何东西。
我做错了什么?或者我的设置中有什么东西阻止了 JMockit 实际上 运行?
我的问题似乎出在 JUnit 的使用上。我什至在没有运气的情况下逐字尝试了教程示例。但是通过转换为 TestNG,我所有的问题都消失了。
似乎 JMockit 的 Expectations 块无法使用 JUnit 正确挂接到代码中。要么无法识别呼叫,要么没有发生伪造。我现在很好奇,有人使用 JUnit 吗?
测试中的实际问题是它混合了来自 JUnit 3 的 API(来自 junit.framework
的任何东西)和 JUnit 4+ (org.junit
)。永远不要这样做。
JMockit 仅支持 JUnit 4 API,不支持过时的 JUnit 3 API。所以,把“extends from junit.framework.TestCase
”去掉就可以了。
顺便说一句,您的 Java IDE 应该警告过这个错误。至少,IntelliJ 会立即显示 "Method 'testGetDtoById()' annotated with '@Test' inside class extending JUnit 3 TestCase".
此外,测试(和被测代码)还有其他几个错误...
我不确定是我没有正确使用 JMockit,还是我的设置有问题。我在 Eclipse 中使用 JMockit 1.32 和 JUnit 4.12。
我的问题似乎是没有捕获接口。具体在 java.sql
包中。例如:
public class Dto {
private int id;
public Dto(){}
public Dto(ResultSet rs) {
try {
id = rs.getInt(1);
} catch (SQLException e) { }
}
public int getId() {return id;}
void setId(int id) {this.id = id;}
}
.
public class ClassUnderTest {
public static Dto loadObject(Connection conn, String tablename, int id) {
Dto result = null;
ResultSet rs = null;
PreparedStatement ps = null;
try {
String sql = "select * from " + tablename + " where id = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
rs = ps.executeQuery();
if (rs.next()) {
result = new Dto(rs);
}
} catch (SQLException e) {
} finally {
try {
if (ps != null) ps.close();
} catch (SQLException e) { }
}
return result;
}
}
.
public class ResultSetTest extends junit.framework.TestCase {
private static final int OBJ_ID = 5;
@Capturing
ResultSet mockResultSet;
@Capturing
PreparedStatement mockStatement;
@Capturing
Connection mockConn;
@Test
public void testGetDtoById() throws SQLException {
new Expectations() {{
mockConn.prepareStatement(anyString); result = mockStatement;
mockStatement.setInt(anyInt, OBJ_ID);
mockResultSet.next(); result = true;
new Dto(mockResultSet); result = new Dto();
mockResultSet.next(); result = true;
}};
Dto dto = ClassUnderTest.loadObject(mockConn, "", OBJ_ID);
assertEquals(dto.getId(), OBJ_ID);
}
}
在此设置中,测试执行失败并在 Expectations(){}
块的第一行出现 NPE。但是从教程等来看,我希望创建一个模拟实例。 (e.g. tutorial)
为了克服这个问题,我创建了显式模拟 类,如下所示:
public class ResultSetMockup extends MockUp<ResultSet> { }
public class PreparedStatementMockup extends MockUp<PreparedStatement>
{
@Mock ResultSet executeQuery() {return new ResultSetMockup().getMockInstance();}
}
public class ConnectionMockup extends MockUp<Connection>
{
@Mock PreparedStatement prepareStatement(String sql) throws SQLException {
return new PreparedStatementMockup().getMockInstance();
}
}
@Capturing
ResultSet mockResultSet = new ResultSetMockup().getMockInstance();
@Capturing
PreparedStatement mockStatement = new PreparedStatementMockup().getMockInstance();
@Capturing
Connection mockConn = new ConnectionMockup().getMockInstance();
在这一点上,Expectations() {}
块是快乐的,但似乎从未真正设置 results
。通过设置断点,我看到 rs.next()
总是失败。所以我认为实际上没有捕获任何东西。
我做错了什么?或者我的设置中有什么东西阻止了 JMockit 实际上 运行?
我的问题似乎出在 JUnit 的使用上。我什至在没有运气的情况下逐字尝试了教程示例。但是通过转换为 TestNG,我所有的问题都消失了。
似乎 JMockit 的 Expectations 块无法使用 JUnit 正确挂接到代码中。要么无法识别呼叫,要么没有发生伪造。我现在很好奇,有人使用 JUnit 吗?
测试中的实际问题是它混合了来自 JUnit 3 的 API(来自 junit.framework
的任何东西)和 JUnit 4+ (org.junit
)。永远不要这样做。
JMockit 仅支持 JUnit 4 API,不支持过时的 JUnit 3 API。所以,把“extends from junit.framework.TestCase
”去掉就可以了。
顺便说一句,您的 Java IDE 应该警告过这个错误。至少,IntelliJ 会立即显示 "Method 'testGetDtoById()' annotated with '@Test' inside class extending JUnit 3 TestCase".
此外,测试(和被测代码)还有其他几个错误...