Java spock测试中的对象比较失败

Java spock测试中的对象比较失败,java,unit-testing,groovy,spock,Java,Unit Testing,Groovy,Spock,我正在尝试使用spock编写一个测试,用于我已有的方法 方法如下所示- InvoiceView getInvoiceDetailView(String invoiceNumber, Boolean isNew) { InvoiceView detailView; if (isNew) { newInvoiceDao.em = billingEm; //call InvoiceDao List<GroovyRowResult&g

我正在尝试使用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);
} ...
最后是斯波克的固定装置。我已经注释掉了令人不快的比较线,并制定了相应的解决方案。我的问题是-为什么我的“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
}

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

您没有正确模拟getInvoice方法。尽管您通过两个参数调用它,但模拟调用只需要一个参数(“\u1”字符接受任何参数,但将正好与一个参数匹配)。由于没有匹配的模拟方法,因此对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
但是,如果我正确模拟concatenate方法,测试将成功:

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

谢谢你的回答,卡洛斯,但我认为这不是解决办法。我不知道为什么把那句话移到then块中会有不同,但我试了一下,没有掷骰子。对不起,我认为这与Spock mocks范围的混乱定义有关。至少这不是直观的。在您理解它之后,这是有道理的,但是我团队中所有与Spock一起工作的开发人员在第一次尝试它时都遇到了问题。这就是我发现的问题所在。我将规范groovy注释粘贴在类定义之上,但这没有帮助,比较检查仍然失败。不知道如何解决这个问题…只需在调试器中运行测试。
Condition not satisfied:

result == "ab"
|      |
null   false
su.concatenate(_, _) >> "ab"