0

我正在尝试使用 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
}
4

2 回答 2

2

equals显然,根据 class的方法,对象并不相等InvoiceView。或者,也许该类没有声明equals方法,并且对象不相同(根据Object.equals)。

于 2012-11-12T21:17:28.357 回答
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"
于 2012-11-13T14:49:54.713 回答