Grails v3.3.9 - 影响实时/开发和集成测试
我的情况是,我有一个集成测试在构建手动创建的记录和从数据库中找到的记录时一直失败,但是如果您在测试中链接两个手动创建的记录,则可以工作。
我一直在尝试一千次调整,并确保 GORM 正在按照文档中所说的进行。
我已经缩减了我的代码并构建了一些更简单的东西,它在结构上看起来像我的真实东西,但基于 GORM 用户指南中的 Airport/Flights 模型(请参阅用户指南中的第 5.1.2节)
像这样声明抽象基类
机场.groovy
abstract class Airport{
String name
Collection<? extends Flight> outboundFlights = []
Collection<? extends Flight> inboundFlights = []
static hasMany = [outboundFlights:Flight, inboundFlights:Flight]
static mappedBy = [outboundFlights: 'departureAirport', inboundFlights: 'arrivalAirport']
static constraints = {
outboundFlights nullable:true
inboundFlights nullable:true
}
static mapping = {
tablePerHierarchy false //multiple tables+joins
}
}
声明一个扩展它的具体类,您可以使用:
UkAirport.groovy
class UkAirport extends Airport {
String shortCode = "dont know"
static constraints = {
}
}
声明具有两个基本相同类型的属性的 Flight 实体
class Flight<A extends Airport> {
String flightCode = "unassigned"
A departureAirport
A arrivalAirport
//setup belongs to
static belongsTo = [departureAirport:Airport, arrivalAirport:Airport]
static constraints = {
}
}
现在是集成测试;有几点需要注意。
1)我在设置中预先创建了一个 UkAirport(没有为它声明航班) 2)我在实际测试中创建了两个手动 UkAirports - Gatwick 和 Stansted 并保存这些 3)我设置了两个航班 - 一个从 Gatwick 到 Stansted,和从我通过执行 UkAirport.get() 找到盖特威克机场以预先保存曼彻斯特
这是奇怪的事情。如果我按此处所示运行此测试 - 它会通过,因为我断言没有飞往曼彻斯特 ( assert manchester.inboundFlights.size() == 0
) 的现有航班。
但是,如果您将该断言注释掉并重新运行,则测试将失败并且它将声明manchester.inboundFlights.size()
等于 2 -
如果我使用调试器也是一样的——如果在执行 flight2.save() 之前停下来看看曼彻斯特,测试将起作用——如果你在 flight2.save() 之后设置断点,则 manchester.inboundFlights 显示 2错误的条目。
class AirportIntegrationSpec extends Specification {
def setup() {
Airport manchester = new UkAirport (name:"Manchester", shortCode:"MAN")
manchester.save(failOnError:true)
}
def cleanup() {
}
void "two airports and one flight "() {
given :
Airport gatwick = new UkAirport (name:"Gatwick", shortCode:"LGW")
Airport stansted = new UkAirport (name:"Stansted", shortCode:"STN")
Airport manchester = UkAirport.get(1L)
assert manchester.shortCode == "MAN"
gatwick.save ()
stansted.save ()
when:
Flight flight = new Flight<UkAirport>(flightCode:"F123-LGW-STN")
gatwick.addToOutboundFlights(flight)
stansted.addToInboundFlights(flight)
flight.save (failOnError:true)
assert gatwick.outboundFlights.size() == 1
assert gatwick.inboundFlights.size() == 0
assert stansted.outboundFlights.size() == 0
assert stansted.inboundFlights.size() == 1
// -all ok until we get to here - if you evaluate manchester before you use it - test works
//if you comment out and use before you evaluate it fails !
assert manchester.inboundFlights.size() == 0 //comment out makes test fail !
Flight flight2 = new Flight<UkAirport>(flightCode:"F789-LGW-MAN")
gatwick.addToOutboundFlights(flight2)
manchester.addToInboundFlights(flight2)
flight2.save (failOnError:true)
assert gatwick.outboundFlights.size() == 2
assert manchester.inboundFlights.size() == 1
then :""
flight.id == 1
flight2.id == 2
gatwick.inboundFlights.size() == 0
gatwick.outboundFlights.size() == 2
stansted.outboundFlights.size() == 0
stansted.inboundFlights.size() == 1
flight.departureAirport.name == "Gatwick"
flight.arrivalAirport.name == "Stansted"
flight2.departureAirport.name == "Gatwick"
flight2.arrivalAirport.name == "Manchester"
}
}
有人可以确认这确实是一个缺陷,我会提出它(代码中的临时工作 - 是访问从数据库中选择的实体 - 然后在你周围建立任何关系之前)。
我的Github 项目在这里,所有这些的集成测试在这里。
这是我之前与Stack Overflow 相关的问题——我将对其进行更新,因为它基本上归结为上述问题。