【问题标题】:Unit testing a method that takes a ResultSet as parameter对以 ResultSet 作为参数的方法进行单元测试
【发布时间】:2017-06-10 22:04:22
【问题描述】:

如何对无法实例化的对象进行单元测试?因为目前我有一个将 ResultSet 转换为对象的方法,但我不确定这是否违反任何编程原则。

public CItem convert(ResultSet rs) {
    CItem ci = new CItem ();

    try {
        ci.setHinumber(rs.getString("id"));
        ci.setHostname(rs.getString("sysname"));
        ci.setOs(rs.getString("zos"));
        ci.setTenant(rs.getString("customer_name"));
        //ci.setInstallation(rs.getField("installation_name"));
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return ci;
}

我是否需要寻找一种不同的方法来解决这个问题,仅仅是因为它无法进行单元测试?或者我可以以某种方式伪造一个 ResultSet 对象。

任何帮助将不胜感激。

【问题讨论】:

  • 模拟一个ResultSet 怎么样?
  • mockResultSet
  • 不知道这是可能的,你会推荐 Mockrunner 吗?
  • 我会推荐Mockito

标签: java unit-testing junit resultset


【解决方案1】:

您可以简单地模拟您的 ResultSet 为每个字段提供一个值并检查结果是否包含您的期望。

例如使用Mockito,您的测试将是这样的:

@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {

    @Mock
    private ResultSet resultSet;

    @Test
    public void testConvert() throws SQLException {
        // Define the behavior of the mock for each getString method's call
        Mockito.when(resultSet.getString("id")).thenReturn("myId");
        Mockito.when(resultSet.getString("sysname")).thenReturn("myHost");
        Mockito.when(resultSet.getString("zos")).thenReturn("myOS");
        Mockito.when(resultSet.getString("customer_name")).thenReturn("myCustomerName");

        // Launch the method against your mock
        SomeClass someClass = new SomeClass();
        CItem item = someClass.convert(resultSet);

        // Check the result
        Assert.assertNotNull(item);
        Assert.assertEquals("myId", item.getHinumber());
        Assert.assertEquals("myHost", item.getHostname());
        Assert.assertEquals("myOS", item.getOs());
        Assert.assertEquals("myCustomerName", item.getTenant());
    }
}

【讨论】:

    【解决方案2】:

    如果您的课程不处理数据库访问,那么接受 ResultSet 作为参数感觉就像代码异味。

    您可以使用 Mockito 或 Power Mock 等模拟框架来创建模拟结果集。但是,您不应该模拟这些您没有编写的类(即库/JDK 类)。

    假设您的 ResultSet 表示来自 Order 表的一些订单数据。这种方法真正需要的是“订单数据”,此时您不必担心如何以及从何处获取这些数据。所以理想情况下你应该定义一个这样的接口。

    interface OrderRepository {
        OrderData get();
    }
    

    然后你可以有一个实现这个接口JDBCOrderRepository的类来处理ResultSet。您的方法('convert')现在将接受 OrderRepository 而不是 ResultSet。为了测试您的方法,您可以模拟 OrderRepository 而不是 ResultSet,这更容易。

    现在你将如何测试JDBCOrderRepository?好吧,也许你应该用一个正在运行的 DB 实例来测试它,这实际上是一个集成测试。

    【讨论】:

      猜你喜欢
      • 2015-08-20
      • 1970-01-01
      • 2016-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多