spock测试中的对象比较失败

时间:2012-11-12 19:05:12

标签: java unit-testing groovy spock

我正在尝试使用spock为我的方法编写测试。

该方法如下所示 -

InvoiceView getInvoiceDetailView(String invoiceNumber, Boolean isNew) {
    InvoiceView detailView;
    if (isNew) {
        newInvoiceDao.em = billingEm;
        //call InvoiceDao
        List<GroovyRowResult> invoiceSummaryRowResult = billingAdmin.rows(InvoiceQueries.GET_NEW_INVOICE_SUMMARIES_BY_NUMBER, [invoiceNumber:invoiceNumber]);
        List<GroovyRowResult> invoiceDetailsRowResult = billingAdmin.rows(InvoiceQueries.GET_NEW_INVOICE_DETAILS_BY_NUMBER, [invoiceNumber:invoiceNumber]);
        InvoiceModel invoiceModel = newInvoiceDao.getInvoice(invoiceNumber);
        detailView = new InvoiceView(invoice:invoiceModel,
                                             summary:invoiceSummaryRowResult,
                                            details:invoiceDetailsRowResult);
} ...

我的测试只是试图断言当调用此方法并将true作为isNew参数的值传入时,将返回一个有效的InvoiceView对象。

在我的spock测试中,我创建了一些我期望从方法返回的对象:

def expectedInvoiceModel = new InvoiceModel()
def expectedInvoiceSummaryRowResult = new ArrayList<GroovyRowResult>()
def expectedInvoiceDetailsRowResult = new ArrayList<GroovyRowResult>()

def expectedInvoiceView = new InvoiceView(invoice:expectedInvoiceModel,
                                          summary:expectedInvoiceSummaryRowResult,
                                          details:expectedInvoiceDetailsRowResult)

我也嘲笑我将要调用的dao对象:

def setup() {
    ...
    service.billingAdmin = Mock(Sql)
    ...
}

所以最后到了Spock夹具上。我对违规的比较线进行了评论并制定了相应的解决方案。我的问题是 - 为什么我的“then”块中的第一行失败了?

def "getInvoiceDetailView returns valid InvoiceView for new invoice"() {
    given:
        service.billingAdmin.rows(InvoiceQueries.GET_NEW_INVOICE_SUMMARIES_BY_NUMBER, [invoiceNumber:invoiceNumber]) >> expectedInvoiceSummaryRowResult
        service.billingAdmin.rows(InvoiceQueries.GET_NEW_INVOICE_DETAILS_BY_NUMBER, [invoiceNumber:invoiceNumber]) >> expectedInvoiceDetailsRowResult
        service.newInvoiceDao.getInvoice(_) >> expectedInvoiceModel

    when:
        def result = service.getInvoiceDetailView(invoiceNumber, true)
    then:
        //result == expectedInvoiceView -- Why doesn't this work?
        result.invoice == expectedInvoiceModel
        result.summary == expectedInvoiceSummaryRowResult
        result.details == expectedInvoiceDetailsRowResult
}

2 个答案:

答案 0 :(得分:1)

显然,根据类equals的{​​{1}}方法,对象不相等。或者该类可能没有声明InvoiceView方法,并且对象不相同(根据equals)。

答案 1 :(得分:0)

扎卡里。

您没有正确模拟getInvoice方法。虽然你调用它传递两个参数,但是你的模拟调用只期望一个(“_”字符接受任何参数,但只与一个参数匹配)。由于没有匹配模拟方法,因此对getInvoice的调用将返回默认值null,从而使测试失败。

您应该执行以下操作以使测试通过:

service.newInvoiceDao.getInvoice(_, _) >> expectedInvoiceModel

我写了一个小测试,以使其更清晰。鉴于以下课程:

private static class StringUtils {
    public String concatenate(String a, String b) {
        return a + b;
    }
}

以下测试将失败:

def "concatenation should work!"() {
    given: 
    StringUtils su = Mock()
    su.concatenate(_) >> "ab"

    when:
    def result = su.concatenate("a", "b")

    then:
    result == "ab" 
}

请注意,我的模拟方法只需要一个参数:

su.concatenate(_) >> "ab"

这是显示我返回空值的错误消息:

Condition not satisfied:

result == "ab"
|      |
null   false

但是,如果我正确地模拟了连接方法,测试将会成功:

su.concatenate(_, _) >> "ab"