Использование asComparatorForType в assertj, по-видимому, не применяется к свойствам объектов, которые являются свойствами объекта - PullRequest
0 голосов
/ 22 мая 2018

Я хочу проверить равенство двух объектов, но по своему усмотрению могу оценить точность значений double, которые присутствуют в некоторых их вложенных свойствах. usingComparatorForType представляется подходящим решением, но оно не работает, если мой Foo объект имеет свойство типа Bar, где Bar.baz - double, и я хочу, чтобы это было на усмотрение точностиприменять к. Пример для isEqualToComparingFieldByFieldRecursively не совсем соответствует ситуации, которую я пытаюсь проверить.

Некоторые примеры кода

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Comparator;
import java.util.Objects;

import org.junit.Test;

public class ComparatorForTypeTest {

  private static final Comparator<Double> DOUBLE_COMPARATOR = new Comparator<Double>() {
    @Override
    public int compare(Double d1, Double d2) {
      return Math.abs(d1 - d2) <= 0.1 ? 0 : 1;
    }
  };

  class Foo {
    private int id;
    private double baz;
    private Bar bar;

    public Foo(int id, double baz, Bar bar) {
      this.id = id;
      this.baz = baz;
      this.bar = bar;
    }

    public Foo withBar(Bar bar) {
      Foo that = this;
      that.bar = bar;
      return that;
    }

    @Override
    public int hashCode() {
      return Objects.hash(id, baz, bar);
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      } else if (obj == null || obj.getClass() != Foo.class) {
        return false;
      }

      Foo that = (Foo) obj;
      return Objects.equals(this.id, that.id)
          && Objects.equals(this.baz, that.baz)
          && Objects.equals(this.bar, that.bar);
    }

    @Override
    public String toString() {
      return String.format("Foo[id=%d, score=%f, bar=%s]", id, baz, bar == null ? null : bar.toString());
    }
  }

  class Bar {
    private int id;
    private double baz;

    public Bar(int id, double baz) {
      this.id = id;
      this.baz = baz;
    }

    @Override
    public int hashCode() {
      return Objects.hash(id, baz);
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      } else if (obj == null || obj.getClass() != Bar.class) {
        return false;
      }

      Bar that = (Bar) obj;
      return Objects.equals(this.id, that.id)
          && Objects.equals(this.baz, that.baz);
    }

    @Override
    public String toString() {
      return String.format("Bar[id=%d, score=%f]", id, baz);
    }
  }

  @Test
  public void itComparesBars() {
    Bar a = new Bar(1, 1.4);
    Bar b = new Bar(1, 1.45);
    Bar c = new Bar(2, 1.4);

    assertThat(a).isNotEqualTo(b);
    assertThat(b).isNotEqualTo(c);
    assertThat(a).isNotEqualTo(c);

    assertThat(a).usingComparatorForType(DOUBLE_COMPARATOR, Double.class).isEqualToComparingFieldByField(b);
  }

  @Test
  public void itComparesFoos() {
    Foo a = new Foo(1, 1.4, null);
    Foo b = new Foo(1, 1.45, null);
    Foo c = new Foo(2, 1.4, null);

    assertThat(a).isNotEqualTo(b);
    assertThat(b).isNotEqualTo(c);
    assertThat(a).isNotEqualTo(c);

    assertThat(a).usingComparatorForType(DOUBLE_COMPARATOR, Double.class).isEqualToComparingFieldByField(b);

    Bar barA = new Bar(1, 1.4);
    Bar barB = new Bar(1, 1.45);

    assertThat(a.withBar(barA)).usingComparatorForType(DOUBLE_COMPARATOR, Double.class).isEqualToComparingFieldByFieldRecursively(b.withBar(barA));
    assertThat(a.withBar(barA)).usingComparatorForType(DOUBLE_COMPARATOR, Double.class).isEqualToComparingFieldByFieldRecursively(b.withBar(barB));
  }
}

В этом случае itComparesFoos - это то место, где я собираюсь применить это усмотрение в отношении точности двойных чисел.

1 Ответ

0 голосов
/ 23 мая 2018

Проблема здесь в том, что Bar имеет переопределенный метод equals, и он используется для сравнения Bar экземпляров, это упоминается в javadoc (но я получаю, что Javadoc не всегдалучший способ обнаружить API):

Рекурсивное сравнение свойств / полей не применяется к полям, имеющим пользовательскую реализацию equals, то есть переопределенный метод equals будет использоваться вместо сравнения полей с полями,

https://github.com/joel-costigliola/assertj-core/issues/1002 - это заявка на реконструкцию API рекурсивного сравнения, которая стала дикой, она предоставит возможность принудительного рекурсивного сравнения, даже если equals был переопределен (вероятно, forcingRecursiveComparisonForAll).

...