0

在我们公司,我们有一个服务层,它接收一些请求 XML,通过 JDBC 访问各种存储过程 (SP),处理数据并使用一些响应 XML 进行响应。最近人们开始在他们的 JUnit 测试中采用 MockRunner 来模拟来自 SP 的响应。使用 MockRunner 从 SP 设置模拟响应的代码看起来很糟糕(这是我打开的第一个随机测试类):

    MockConnection connection = new MockConnection();
    MockContextFactory.setAsInitial();
    InitialContext context = new InitialContext();
    context.rebind(READ_PAYMENT_DATA_SOURCE, getDS());
    getDS().setupConnection(connection);
    m_csStatementHandler = connection.getCallableStatementResultSetHandler();
    m_csStatementHandler.clearResultSets();
    m_csStatementHandler.clearCallableStatements();
    m_csStatementHandler.setExactMatch(false);
 m_csStatementHandler.prepareReturnsResultSet(READ_PAYMENT, true);
    m_csStatementHandler.setExactMatch(false);
    m_csStatementHandler.setExactMatchParameter(false);
    Map parameterMap = new HashMap();
    parameterMap.put(new Integer(1), null);
    parameterMap.put(new Integer(2), null);
    parameterMap.put(new Integer(3), null);
    parameterMap.put(new Integer(4), null);
    m_csStatementHandler.prepareOutParameter(READ_PAYMENT, parameterMap);
    //Set up the cursor of applications for return.
    MockResultSet resultApps = m_csStatementHandler.createResultSet();  

    resultApps.addRow(getPaymentSchedule("E", "Monthly", new Short("1"),null,null,null,null,null,null,null));
    resultApps.addRow(getPaymentSchedule("A", "Weekly", new Short("1"),null,null,null,null,null,null,null));
    resultApps.addRow(getPaymentSchedule("R", "Yearly", new Short("1"),null,null,null,null,null,null,null));
    resultApps.addRow(getPaymentSchedule("S", "Weekly", new Short("1"),null,null,null,null,null,null,null));
    resultApps.addRow(getPaymentSchedule("W", "Monthly", new Short("1"),null,null,null,null,null,null,null));

    MockResultSet[] results = new MockResultSet[1];
    results[0] = resultApps;
    m_csStatementHandler.prepareResultSet(READ_PAYMENT, resultApps);   

上面的代码很糟糕,原因有很多,但它确实清楚地显示了设置存储过程响应的复杂性和开销。

迄今为止,我一直在使用手动依赖注入来注入实际调用存储过程的类。我所要做的就是创建一个模拟 SP 调用程序类(负责 SP 的实际执行)并设置我想要的响应数据。我对这种技术非常满意,而且它比上面的更简单,因为它专注于数据而不是担心实现细节。但我的问题是,你什么时候想使用 MockRunner?单元测试似乎有点矫枉过正,所以我猜它更多地用于集成或系统测试?即便如此,我仍然觉得使用 DI 框架替换 SP 调用程序类然后为每个存储过程调用设置上面的所有代码更容易。请赐教!谢谢

4

1 回答 1

3

最终,您正在研究一般嘲笑背后的哲学。我会给你两分钱,但我也会向你推荐任何主要的模拟库,这可能会为它们自己的存在提供很好的理由。以Mockito为例。

测试/模拟社区通常会区分您手动滚动的内容,通常称为“存根”(静态的、手写的类)与“模拟”(动态的、运行时生成的类)。

与存根相比,模拟的好处是相当大的。许多测试人员对仅仅为了测试目的而编写接口实现和/或子类具体类的想法感到恼火。这样做通常需要实现所述类/接口的所有方法,即使您只想测试特定方法。

Mocking 可以让你通过定义你想要赋予行为的方法来解决这个问题,这很强大。此外,模拟允许您将行为从一个测试更改为下一个测试。要使用存根来做到这一点,您必须编写一个全新的存根类。

从模拟库到库,语法略有不同。有些你可能会发现比其他的更具可读性。我目前最喜欢的是 Mockito,因此是较早的参考,但它们会随着时间的推移而发展。可能值得确定您的组织为什么使用模拟套件,以及另一个是否仍然可以满足您的需求并且更具可读性。

希望您的测试编写者将通用行为引入测试设置方法(如 JUnit 的 @Before),这样您就不必到处看到模拟创建和通用初始化。

于 2010-08-03T21:48:29.253 回答