GORM公式未计算

时间:2014-10-16 15:42:16

标签: grails gorm formula

我有以下Grails 2.4.3 Domain类

package invoicer

class Product {
    Float price
    Float taxRate
    Float tax

    static mapping = {
        tax formula: 'PRICE * TAX_RATE'
    }
}

我已创建此集成测试以验证公式是否正确计算

package invoicer;

import spock.lang.Specification

class ProductIntegrationSpec extends Specification {

    def "Test tax calculation"() {
        when:
        def p = new Product(price: 5.00, taxRate: 0.25)
        p.save(failOnError:true, flush: true)

        then:
        def newProduct = Product.get(1)
        newProduct.tax == (5.00 * 0.25)
    }
}

此测试总是失败

grails> test-app -integration ProductIntegrationSpec
2014-10-16 11:29:15,225 [main] DEBUG hibernate.SQL  - 
    drop table product if exists
2014-10-16 11:29:15,230 [main] DEBUG hibernate.SQL  - 
    create table product (
        id bigint generated by default as identity,
        version bigint not null,
        price float not null,
        tax_rate float not null,
        primary key (id)
    )
======================================================================
                      Application: Invoicer 0.1                       
                      -------------------------                       
  Environment: TEST
  Database configuration: 
    Hibernate DDL mode: create
    URL: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
    Driver: org.h2.Driver
    User: sa
======================================================================
| Running 1 integration test... 1 of 1
2014-10-16 11:29:17,797 [main] DEBUG hibernate.SQL  - 
    /* insert invoicer.Product
        */ insert 
        into
            product
            (id, version, price, tax_rate) 
        values
            (null, ?, ?, ?)
2014-10-16 11:29:17,798 [main] TRACE sql.BasicBinder  - binding parameter [1] as [BIGINT] - [0]
2014-10-16 11:29:17,798 [main] TRACE sql.BasicBinder  - binding parameter [2] as [FLOAT] - [5.0]
2014-10-16 11:29:17,798 [main] TRACE sql.BasicBinder  - binding parameter [3] as [FLOAT] - [0.25]
| Failure:  Test tax calculation(invoicer.ProductIntegrationSpec)
|  Condition not satisfied:
newProduct.tax == (5.00 * 0.25)
|          |   |        |
|          |   false    1.2500
|          null
invoicer.Product : 1
    at invoicer.ProductIntegrationSpec.Test tax calculation(ProductIntegrationSpec.groovy:14)
| Completed 1 integration test, 1 failed in 0m 0s
| Tests FAILED  - view reports in /Users/XXX/git/invoicer/target/test-reports

我不明白为什么会失败,所以我在Grails控制台中尝试了这段代码

import invoicer.*

def p = new Product(price: 5.00, taxRate: 0.25)
p.save(failOnError: true, flush: true)

def newProduct = Product.get(1)
assert newProduct.tax == (5.00 * 0.25)

它以第一次在控制台中运行

的方式失败

groovy>     import invoicer.* 
groovy>      
groovy>     def p = new Product(price: 5.00, taxRate: 0.25) 
groovy>     p.save(failOnError: true, flush: true) 
groovy>      
groovy>     def newProduct = Product.get(1) 
groovy>     assert newProduct.tax == (5.00 * 0.25) 

2014-10-16 11:34:31,140 [Thread-12] DEBUG hibernate.SQL  - 
    /* insert invoicer.Product
        */ insert 
        into
            product
            (id, version, price, tax_rate) 
        values
            (null, ?, ?, ?)

2014-10-16 11:34:31,162 [Thread-12] TRACE sql.BasicBinder  - binding parameter [1] as [BIGINT] - [0]

2014-10-16 11:34:31,163 [Thread-12] TRACE sql.BasicBinder  - binding parameter [2] as [FLOAT] - [5.0]

2014-10-16 11:34:31,164 [Thread-12] TRACE sql.BasicBinder  - binding parameter [3] as [FLOAT] - [0.25]

Exception thrown

Assertion failed: 

assert newProduct.tax == (5.00 * 0.25)
       |          |   |        |
       |          |   false    1.2500
       |          null
       invoicer.Product : 1

    at ConsoleScript0.run(ConsoleScript0:7)
    at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1270)

虽然在同一个控制台会话中再次运行,但它的工作正常!

groovy>     import invoicer.* 
groovy>      
groovy>     def p = new Product(price: 5.00, taxRate: 0.25) 
groovy>     p.save(failOnError: true, flush: true) 
groovy>      
groovy>     def newProduct = Product.get(1) 
groovy>     assert newProduct.tax == (5.00 * 0.25) 

2014-10-16 11:36:20,612 [Thread-13] DEBUG hibernate.SQL  - 
    /* insert invoicer.Product
        */ insert 
        into
            product
            (id, version, price, tax_rate) 
        values
            (null, ?, ?, ?)

2014-10-16 11:36:20,613 [Thread-13] TRACE sql.BasicBinder  - binding parameter [1] as [BIGINT] - [0]

2014-10-16 11:36:20,613 [Thread-13] TRACE sql.BasicBinder  - binding parameter [2] as [FLOAT] - [5.0]

2014-10-16 11:36:20,614 [Thread-13] TRACE sql.BasicBinder  - binding parameter [3] as [FLOAT] - [0.25]

2014-10-16 11:36:20,620 [Thread-13] DEBUG hibernate.SQL  - 
    select
        product0_.id as id1_7_0_,
        product0_.version as version2_7_0_,
        product0_.price as price3_7_0_,
        product0_.tax_rate as tax_rate4_7_0_,
        product0_.PRICE * product0_.TAX_RATE as formula0_0_ 
    from
        product product0_ 
    where
        product0_.id=?

2014-10-16 11:36:20,621 [Thread-13] TRACE sql.BasicBinder  - binding parameter [1] as [BIGINT] - [1]

请注意,第二次运行会记录一个select语句,其中计算税额,但第一次运行时没有;我很难说第一次控制台行为失败的原因以及它第二次正常运行的原因。我想这个问题的答案可以解释为什么集成测试总是失败。谢谢你的想法!

1 个答案:

答案 0 :(得分:3)

我终于明白了。致电

save(flush: true) 

还不够。关键是重新查询数据库,因为这是where子句生成公式的时候。保存域对象后,必须调用

refresh() 

就可以了。重新查询数据库并填充基于公式的字段。