2

I'm stuck trying to get the second test of the code below to work.

Both have the same payload structure, the one that works use Map<> only, the second one uses classes.

Why does the first test work but the second doesn't?

It seems a bug with usingRecursiveFieldByFieldElementComparator.

package com.example.hi;

import com.example.hi.ExampleTest.Foo.Bar;
import lombok.AllArgsConstructor;
import lombok.Value;
import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;

public class ExampleTest {

    Comparator<LocalDateTime> truncateSeconds = (a, exp) ->
        a.isAfter(exp.truncatedTo(ChronoUnit.SECONDS)) ? 0 : 1;

    @Test
    void works() {

        var a = Map.of("values", Map.of("one", singletonList(Map.of("date", LocalDateTime.now()))));
        var b = Map.of("values", Map.of("one", singletonList(Map.of("date", LocalDateTime.now()))));

        assertThat(singletonList(a))
            .usingRecursiveFieldByFieldElementComparator()
            .usingComparatorForElementFieldsWithType(truncateSeconds, LocalDateTime.class)
            .containsExactly(b);
    }

    @Test
    void works_not() {

        var a = new Foo(Map.of("one", singletonList(new Bar(LocalDateTime.now()))));
        var b = new Foo(Map.of("one", singletonList(new Bar(LocalDateTime.now()))));

        assertThat(singletonList(a))
            .usingRecursiveFieldByFieldElementComparator()
            .usingComparatorForElementFieldsWithType(truncateSeconds, LocalDateTime.class)
            .containsExactly(b);
    }

    @Value
    @AllArgsConstructor
    public static class Foo {

        Map<String, List<Bar>> values;

        @Value
        @AllArgsConstructor
        public static class Bar {

            LocalDateTime date;
        }
    }
}
Fabricio
  • 7,705
  • 9
  • 52
  • 87
  • I believe comparators do not match for both cases. You should try with a specific comparator for "Bar" for the second case – Dogukan Zengin May 16 '20 at 11:04
  • 1
    @DogukanZengin if so, that would be unfortunate, because I'd expect `usingRecursiveFieldByFieldElementComparator` to go deep for every and each field, as it's name implies. – Fabricio May 16 '20 at 11:07
  • you are so right – Dogukan Zengin May 16 '20 at 11:12
  • 1
    I just figured out that if I change `@lombok.Value` to `@lombok.Getter` it works. So it seems usingRecursiveFBFEC first checks for the hash/equals() before going down to fields. Idk if that makes sense for its funcionality – Fabricio May 16 '20 at 12:26
  • 2
    Fabricio, thanks for creating an AssertJ issue (https://github.com/joel-costigliola/assertj-core/issues/1876). Nothing obviously wrong, will require in depth analysis. – Joel Costigliola May 17 '20 at 11:40

1 Answers1

2

The issue has been fixed in AssertJ Core 3.17.0 and the following should work:

// static import RecursiveComparisonConfiguration.builder
RecursiveComparisonConfiguration configuration = builder().withIgnoreAllOverriddenEquals(true)
                                                          .withComparatorForType(truncateSeconds, LocalDateTime.class)
                                                          .build();

assertThat(list).usingRecursiveFieldByFieldElementComparator(configuration)
                .containsExactly(b);
Stefano Cordio
  • 1,687
  • 10
  • 20