我有以下的Grails 2.4.3域类GORM公式没有计算
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控制台w第i个验证码
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语句记录了第二次运行的计算税,但没有第一次运行!我很难理解第一次为什么控制台行为失败,为什么它第二次正常运行。我想这个问题的答案会解释为什么集成测试总是失败。谢谢你的想法!
只是一些无关的建议:永远不要使用浮动货币计算。早于后来,你会追逐便士错误或更糟。使用'BugDecimal'。 – cfrick 2014-10-16 21:01:26
感谢您的回复@cfrick。是的,Float是不好的,但是这个问题让我陷入了困境很长一段时间,我退化到使用GORM文档中的例子。 – 2014-10-17 01:36:31