Grails集成测试 - 域对象相等

时间:2013-05-01 19:16:51

标签: grails integration-testing grails-domain-class

设置一些集成测试,我遇到了域类相等的问题。在正常执行期间,相等性按预期工作,但在通过集成测试测试Service方法时,相等性测试将返回false。

一个服务(在测试用例的setUp()中调用)将一个Domain对象放入会话

SomeService {
  setSessionVehicle(String name) {
    Vehicle vehicle = Vehicle.findByName(name)
    session.setAttribute("SessionVehicle", vehicle)
  }

  getSessionVehicle() {
    return session.getAttribute("SessionVehicle")
  }
}

在其他服务的其他地方,我加载一个对象并确保关联的属性对象与会话值匹配:

OtherService {
  getEngine(long id) {
    Vehicle current = session.getAttribute("SessionVehicle")

    Engine engine = Engine.get(id)
    if(!engine.vehicle.equals(current)) throw Exception("Blah blah")
  }
}

这在正常操作期间按预期工作,防止加载错误的引擎(好吧,我清理了类名,假装它有意义)。但是在集成测试中,.equals()在成功时会失败:

Vehicle testVehicle

setUp() {
  Vehicle v = new Vehicle("Default")
  v.save()
  someService.setSessionVehicle("Default")
  testVehicle = someService.getSessionVehicle()
}

testGetEngine() {
  List<Engine> engines = Engine.findAllByVehicle(testVehicle)
  //some assertions and checks
  Engine e = otherService.getEngine(engines.get(0).id)
}

findAll()调用正确地返回会话中与车辆关联的所有引擎的列表,但是当我尝试按ID查找单个引擎时,找到会话车辆与车辆的相等性检查引擎失败。此时只创建了一辆车,并且Exception消息显示会话Vehicle和Engine.Vehicle存在并且值相同。

如果我在testCase本身尝试此等式检查,它会失败,但我可以更改testCase以检查成功的if(vehicle.id == sessionVehicle.id),但我并不热衷于更改我的生产代码以便满足整合测试。

在我的测试用例中设置这些域对象时,我做错了什么,我应该采取不同的做法?

1 个答案:

答案 0 :(得分:3)

首先,您正在进行的等式检查只是检查引用。您不应该使用默认的equals方法进行检查,更好地覆盖域类中的equals方法。

有两种方法可以覆盖equals方法:
1)您可以使用IDE自动生成equals方法的代码(很多空检查等)  2)首选方式:您可以使用Apache Commons项目中的EqualsBuilder和HashCodeBuilder类。该库应该已经可供您的应用程序使用,或者下载JAR文件并放在lib中。
以下是使用EqualsBuilder的示例代码:

            boolean equals(o) {
               if ( !(o instanceof Vehicle) ) {
                  return false
               }
               def eb = new EqualsBuilder()
               eb.append(id, o.id)
               eb.append(name, o.name)
               eb.append(otherProperties, o.otherProperties)
            ....
               return eb.isEquals()
            }

另一点是:你如何在服务中获得会话?来自RequestContextHolder?最好不要直接从服务访问会话,而是将值作为方法参数发送到服务中。