gpt4 book ai didi

groovy - Spock 框架可以进行对象深度比较吗?

转载 作者:行者123 更新时间:2023-12-02 09:58:43 25 4
gpt4 key购买 nike

如何使用 spock 检查深层对象相等性。

假设我们有一个 super 简单的测试,可以与相同的人物对象进行比较

def "A persons test"() {
setup:
def person1 = new Person("Foo", new Address("Bar"))
def person2 = new Person("Foo", new Address("Bar"))

expect:
person1 == person2
}

测试失败

Condition not satisfied:

person1 == person2
| | |
| | Person@6bedbc4d
| false
Person@57af006c

这看起来是一种非常自然的主张平等的方式。

开始使用 spock 的主要原因之一是避免编写大量 hamcrest 样板匹配器代码。

最佳答案

Spock 没有用于执行深度对象比较的内置机制,因为定义对象相等性超出了任何测试框架的范围。你可以做各种各样的事情。

1。这两个类都是 Groovy 类

如果您的两个类(PersonAddress)都是 Groovy 类,您可以生成 equalshashCode 方法在两个类上使用 @EqualsAndHashCode 注释,例如:

import groovy.transform.EqualsAndHashCode
import groovy.transform.TupleConstructor
import spock.lang.Specification

class PersonSpec extends Specification {

def "a person test"() {
setup:
def person1 = new Person("Foo", new Address("Bar"))
def person2 = new Person("Foo", new Address("Bar"))

expect:
person1 == person2
}

@TupleConstructor
@EqualsAndHashCode
static class Person {
String name
Address address
}

@TupleConstructor
@EqualsAndHashCode
static class Address {
String city
}
}

这只是在 Groovy 中实现这两种方法的便捷替代方案。

2。这两个类都是 Java 类

如果你想用 == 运算符比较两个对象,那么你必须在两个类中定义 equalshashCode 方法,比如像:

public final class Person {

private final String name;
private final Address address;

public Person(String name, Address address) {
this.name = name;
this.address = address;
}

public String getName() {
return name;
}

public Address getAddress() {
return address;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Person person = (Person) o;

if (name != null ? !name.equals(person.name) : person.name != null) return false;
return address != null ? address.equals(person.address) : person.address == null;
}

@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (address != null ? address.hashCode() : 0);
return result;
}

static class Address {
private final String city;

public Address(String city) {
this.city = city;
}

public String getCity() {
return city;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Address address = (Address) o;

return city != null ? city.equals(address.city) : address.city == null;
}

@Override
public int hashCode() {
return city != null ? city.hashCode() : 0;
}
}
}

在此示例中,这两种方法都是使用 IntelliJ IDEA“生成 equals 和 hashCode”命令定义的。

3。我可以使用 Lombok !

如果您不想手动定义这两种方法(因为例如您必须记住在修改类字段时更改它们),那么您可以使用 Lombok's @EqualsAndHashCode annotation它的作用类似于 Groovy 的注释,但可以应用于任何 Java 类。

4。我想保留默认的 equalshashCode 方法

那么,在这种情况下,您可以尝试各种方法:

  1. 您可以尝试逐个字段比较这两个对象,例如:

    class PersonSpec extends Specification {

    def "a person test"() {
    setup:
    def person1 = new Person("Foo", new Address("Bar"))
    def person2 = new Person("Foo", new Address("Bar"))

    expect:
    person1.name == person2.name

    and:
    person1.address.city == person2.address.city
    }

    @TupleConstructor
    static class Person {
    String name
    Address address
    }

    @TupleConstructor
    static class Address {
    String city
    }
    }
  2. 您可以尝试使用第三方工具,例如 Unitils reflection assertion

  3. 这可能听起来很奇怪,但您可以比较两个对象的 JSON 表示形式,例如:

    import groovy.json.JsonOutput
    import groovy.transform.TupleConstructor
    import spock.lang.Specification

    class PersonSpec extends Specification {

    def "a person test"() {
    setup:
    def person1 = new Person("Foo", new Address("Bar"))
    def person2 = new Person("Foo", new Address("Bar"))

    expect:
    new JsonOutput().toJson(person1) == new JsonOutput().toJson(person2)
    }

    @TupleConstructor
    static class Person {
    String name
    Address address
    }

    @TupleConstructor
    static class Address {
    String city
    }
    }

无论如何,我绝对建议以一种或另一种方式定义equalshashCode并简单地使用==运算符。希望对您有所帮助。

关于groovy - Spock 框架可以进行对象深度比较吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47375036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com