Reputation: 373
I'm trying to write a test using spock for a method I have.
The method looks like this -
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);
} ...
My test is simply trying to assert that when this method is called with true passed in as the value for the isNew parameter, a valid InvoiceView object is returned.
In my spock test I create some objects which I expect to be returned from the method :
def expectedInvoiceModel = new InvoiceModel()
def expectedInvoiceSummaryRowResult = new ArrayList<GroovyRowResult>()
def expectedInvoiceDetailsRowResult = new ArrayList<GroovyRowResult>()
def expectedInvoiceView = new InvoiceView(invoice:expectedInvoiceModel,
summary:expectedInvoiceSummaryRowResult,
details:expectedInvoiceDetailsRowResult)
I also mock the dao object which I will be calling into:
def setup() {
...
service.billingAdmin = Mock(Sql)
...
}
So finally onto the Spock fixture. I have the offending comparison line commented out and a work around in place. My question is - why does the first line in my "then" block fail?
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
}
Upvotes: 0
Views: 5527
Reputation: 1033
Zachary.
You didn't mock the getInvoice method correctly. Although you invoke it passing two parameters, your mocked call is expecting only one (the "_" character accepts any parameter, but will match against exactly one). Since no mocked method is matched, the call to getInvoice will return the default value, null, making your test fail.
You should do the following to make your test pass:
service.newInvoiceDao.getInvoice(_, _) >> expectedInvoiceModel
I have written a small test to make that more clear. Given the following class:
private static class StringUtils {
public String concatenate(String a, String b) {
return a + b;
}
}
the following test will fail:
def "concatenation should work!"() {
given:
StringUtils su = Mock()
su.concatenate(_) >> "ab"
when:
def result = su.concatenate("a", "b")
then:
result == "ab"
}
Notice that my mocked method, expects only one parameter:
su.concatenate(_) >> "ab"
This is the error message showing that I got a null value back:
Condition not satisfied:
result == "ab"
| |
null false
However, if I mock the concatenate method properly the test will succeed:
su.concatenate(_, _) >> "ab"
Upvotes: 0
Reputation: 123996
Apparently, the objects aren't equal as per the equals
method of class InvoiceView
. Or maybe that class doesn't declare an equals
method, and the objects aren't identical (as per Object.equals
).
Upvotes: 2