简体   繁体   中英

Getting the result of a domain entity in grails unit test

My service would throw an InvalidOperationException if the result of the query PaymentDetails.findByIdAndAmountDateCreatedGreaterThanEquals is NOT NULL

The function aims to check if there are duplicate details from the last 5 minutes. I'm trying to create a unit test for this but the function always returns NULL instead

        given:
        DateUtils.getCurrentDate() >> new Date()
        Date currentDate = new Date()
        Date twoMinutesBeforeCurrentDate = new Date()
        use (TimeCategory) {
            twoMinutesBeforeCurrentDate = currentDate - 2.minutes
        }

        long methodId = 3L
        BigDecimal amount = new BigDecimal("5")

        PaymentDetails details = new PaymentDetails(amount: amount, id:methodId).save(flush: true)

        details.dateCreated = twoMinutesBeforeCurrentDate
        details.save(flush: true)

        when:
        service.validateTransactionDetails(methodId, amount)

        then:
        InvalidOperationException exception = thrown()
        ApiError.SAME_PAYMENT_DETAILS_WITH_PREVIOUS_TRANSACTION == exception.apiError

Here is my service method:

    Date currentDate = DateUtils.getCurrentDate()
    Date fiveMinutesBeforeCurrentDate = null

    use (TimeCategory) {
         fiveMinutesBeforeCurrentDate = currentDate-5.minutes
    }

    PaymentDetails details = PaymentDetails.findByIdAndAmountDateCreatedGreaterThanEquals(methodId, amount, fiveMinutesBeforeCurrentDate)

    if (details) {
        throw new InvalidOperationException(ApiError.SAME_PAYMENT_DETAILS_WITH_PREVIOUS_TRANSACTION)
    }

Thank you in advance. It's my first time debugging something from Grails and I'm having a hard time on this. Please be gentle. Lol.

The problem is that new PaymentDetails(amount: amount, id:methodId) isn't really valid because id s are by default excluded from mass property binding so your PaymentDetails instance does not have the id you think it does (you can verify that by inspecting the object in the debugger if you like). A better idea is to let the entity be assigned an id by the save method and then retrieve that value later to initiate the query. This works:

import grails.testing.gorm.DataTest
import grails.testing.services.ServiceUnitTest
import groovy.time.TimeCategory
import spock.lang.Specification

class PaymentServiceSpec extends Specification implements ServiceUnitTest<PaymentService>, DataTest{

    @Override
    Class[] getDomainClassesToMock() {
        [PaymentDetails]
    }

    void "test payment details validation"() {
        given:
        Date currentDate = new Date()
        GroovySpy(DateUtils, global: true)
        1 * DateUtils.getCurrentDate() >> currentDate

        Date twoMinutesBeforeCurrentDate
        use (TimeCategory) {
            twoMinutesBeforeCurrentDate = currentDate - 2.minutes
        }

        BigDecimal amount = new BigDecimal("5")

        PaymentDetails details = new PaymentDetails(amount: amount).save(flush: true)

        when:
        service.validateTransactionDetails(details.id, amount)

        then:
        InvalidOperationException exception = thrown()
        ApiError.SAME_PAYMENT_DETAILS_WITH_PREVIOUS_TRANSACTION == exception.apiError
    }
}

I hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM