在单元测试中比较对象的正确方法

时间:2011-07-13 19:53:51

标签: java unit-testing grails junit

我正在为我的grails应用程序编写单元测试,并且我意识到我并不知道确定对象是否是正确对象的正确方法。

例如,鉴于此测试:

void testExampleTest() {
    mockSession.person = new Person(firstName:'John', lastName:'Doe', middleInitial:'E')
    def model = controller.testMethod()
    ...assertions...
}

def testMethod = {
    Person currPerson = session.getAttribute("person")
    render(view:'view',model:[person:currPerson]
}

我应该如何确保我添加到会话中的人物对象在模型中正确传递?是否足以使用

assertEquals( person,model['person'] )

或者因为我自己将对象注入会话中使用

更有意义
assertEquals( person.firstName, model['person'].firstName )
assertEquals( person.lastName, model['person'].lastName )
assertequals( person.middleName, model['person'].middleName )

在我看来,只要对象具有正确定义的equals方法,第一种方法就足够了,但我只想看看传统方法是什么。

由于

8 个答案:

答案 0 :(得分:4)

每次测试都需要重复逐个属性的比较 - 所以这是一个很好的旧代码重复,a test smell described in XUnitPatterns。最好有一个合适的equals()

当然,您可以在运行时添加实用程序方法personEquals()甚至覆盖Person.equals()。对于模拟课程,您可能必须这样做。我个人坚持使用更短的代码,如果可能的话只需要assertEquals()

答案 1 :(得分:2)

很有趣,我和一位同事今天也有过类似的讨论。我们的结论是

逐个属性比较费力的一个优点是它报告了一个特定的差异,而不仅仅是“不,它们不等于”,这可能很方便。

此外,我们无法控制某些类,其中一些类缺少等号方法。

我们打算调查是否可以使用反射来实现比较器,从而消除一些单调乏味。

答案 2 :(得分:2)

我发现通过财产做财产更加可靠,并且可以让你对比较某些事情有一点点精细控制,不利的是,设置和维护的工作要多一些

答案 3 :(得分:1)

如果正确定义了等号,那你就是对的。问题是,如果正确定义了equals(意味着它的行为与你期望的一样),你可能必须先进行单元测试。

如果为Person类创建一个模型,这可能会变得更加困难。在这种情况下,您不关心equals是否正常工作,因为您只想检查是否正确设置/访问了某些属性。这就是为什么我更喜欢在可能和必要时检查原始值。我发现它使测试更具描述性(虽然它可能变得非常冗长)。

答案 4 :(得分:1)

在这个特定的实例中,测试单个属性只是一种识别对象特定实例的方法,它会覆盖测试的含义。您特别关注并且应断言的是model['person']与您最初作为person输入的内容完全相同的对象:

assertSame(person, model['person'])

或者使用Hamcrest,它可以提供更具表现力的断言:

assertThat(model['person'], sameInstance(person))

答案 5 :(得分:0)

正如您所写,如果测试数据具有正确的equals方法,您可以使用它。这里的“正确”意味着它会测试您想要测试的属性。

我经常使用仅比较其ID属性的数据库实体。使用这些对象,我需要分别测试每个属性以查看它们是否相等。我写了一个小助手,允许我为许多属性编写一个断言,如:

assertEqualProperties(person, model['person'], "firstName", "lastName", "middleName");

这个帮助器方法使用反射来访问属性(不是直接,我调用commons-beans库)。在Groovy中,肯定有一种语法不需要显式反射。该方法将第一个不相等的属性报告为测试失败。

答案 6 :(得分:0)

在Grails中,每个对象都是可序列化的,因此您可以使用XML序列化比较两者:

public void compareXML(Object a, Object b)
    ByteArrayOutputStream aBaos = new ByteArrayOutputStream();
    XMLEncoder aEncoder = new XMLEncoder(aBaos);
    aEncoder.writeObject(a);
    aEncoder.close();
    String xmlA = baos.toString();

    ByteArrayOutputStream bBaos = new ByteArrayOutputStream();
    XMLEncoder bEncoder = new XMLEncoder(bBaos);
    bEncoder.writeObject(b);
    bEncoder.close();
    String xmlB = bBaos.toString();

    assertEquals(xmlA, xmlB);
}

如果您在eclipse中工作,您将获得两个显示所有差异的XML字符串的文本比较。

答案 7 :(得分:0)

我使用assertSame()。逐字段比较比必要的工作更多 - 你模拟了数据,所以只是断言模拟的值被正确返回。