Grails集成测试-域对象相等 [英] Grails integration test - domain object equality

查看:76
本文介绍了Grails集成测试-域对象相等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Setting up some integration tests, I'm having issues with domain class equality. The equality works as expected during normal execution, but when testing the Service methods through an integration test, the test for equality is coming back false.

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

One service (called in the setUp() of the Test Case) puts a Domain object into the session

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

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

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

Elsewhere in another service, I load an object and make sure the associated attribute object matches the session value:

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

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

这在正常运行期间可以按预期工作,从而防止加载错误的引擎(好吧,我已经清理了类名,假装这是有道理的).但是在集成测试中,该.equals()应该成功时会失败:

This works as expected during normal operation, preventing from loading the wrong engine (Ok, I sanitized the class names, pretend it makes sense). But in the integration test, that .equals() fails when it should succeed:

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查找单个引擎时,在找到的引擎上对会话车辆与车辆"进行的相等性检查失败.此时仅创建了一个车辆,并且异常"消息显示会话Vehicle和Engine.Vehicle存在并且具有相同的值.

The findAll() call is correctly returning the list of all Engines associated with the vehicle in the session, but when I try to look up an individual Engine by ID, the equality check for session Vehicle vs Vehicle on the found Engine fails. Only a single vehicle has been created at this point and the Exception message displays that the session Vehicle and the Engine.Vehicle exist and are the same value.

如果我尝试在testCase本身中进行此相等性检查,它将失败,但是我可以更改testCase以检查成功的if(vehicle.id == sessionVehicle.id),但是我不热衷于更改生产代码来满足集成测试.

If I attempt this equality check in the testCase itself, it fails, but I'm able to change the testCase to check if(vehicle.id == sessionVehicle.id) which succeeds, but I'm not keen on changing my production code in order to satisfy an integration test.

在测试用例中设置这些域对象时,我做错了吗?

Am I doing something wrong when setting up these domain objects in my test case that I should be doing differently?

推荐答案

首先,您所做的相等性检查只是检查引用.您不应该使用默认的equals方法进行检查,最好覆盖域类中的equals方法.

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

First of all, the equality check you are doing is just checking the reference. You should not use the default equals method for your check, better override the equals method in domain class.

There are two ways you can override the equals method:
1) you can use your IDE to auto-generate code for equals method(a lot of null checking etc..).
2) Preferred way: You can use EqualsBuilder and HashCodeBuilder classes from the Apache Commons project. The library should be already available to your application, or download the JAR file and place in lib.
Here is sample code for using 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吗?最好不要直接从服务访问会话,而是在服务中将值作为方法参数发送.

Another point is: how you are getting session in service? from RequestContextHolder? Its a good practice to not access session directly from service, rather send the value as method parameter in the service.

这篇关于Grails集成测试-域对象相等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆