Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test that either one thing holds or another in AssertJ

I am in the process of converting some tests from Hamcrest to AssertJ. In Hamcrest I use the following snippet:

assertThat(list, either(contains(Tags.SWEETS, Tags.HIGH))
    .or(contains(Tags.SOUPS, Tags.RED)));

That is, the list may be either that or that. How can I express this in AssertJ? The anyOf function (of course, any is something else than either, but that would be a second question) takes a Condition; I have implemented that myself, but it feels as if this should be a common case.

like image 388
Michael Piefel Avatar asked Nov 04 '14 11:11

Michael Piefel


People also ask

Why AssertJ?

AssertJ provides a rich set of assertions, truly helpful error messages, improves test code readability and is designed to be super easy to use within your favorite IDE. Get started right away with the one minute starting guide, have a look at some of AssertJ great features or stay up to date with the latest releases.

What is Hamcrest library?

Hamcrest is a framework that assists writing software tests in the Java programming language. It supports creating customized assertion matchers ('Hamcrest' is an anagram of 'matchers'), allowing match rules to be defined declaratively. These matchers have uses in unit testing frameworks such as JUnit and jMock.


1 Answers

Edited:

Since 3.12.0 AssertJ provides satisfiesAnyOf which succeeds is one of the given assertion succeeds,

assertThat(list).satisfiesAnyOf(
    listParam -> assertThat(listParam).contains(Tags.SWEETS, Tags.HIGH),
    listParam -> assertThat(listParam).contains(Tags.SOUPS, Tags.RED)
);

Original answer:

No, this is an area where Hamcrest is better than AssertJ.

To write the following assertion:

Set<String> goodTags = newLinkedHashSet("Fine", "Good");
Set<String> badTags = newLinkedHashSet("Bad!", "Awful");
Set<String> tags = newLinkedHashSet("Fine", "Good", "Ok", "?");

// contains is statically imported from ContainsCondition
// anyOf succeeds if one of the conditions is met (logical 'or') 
assertThat(tags).has(anyOf(contains(goodTags), contains(badTags)));

you need to create this Condition:

import static org.assertj.core.util.Lists.newArrayList;    
import java.util.Collection;    
import org.assertj.core.api.Condition;

public class ContainsCondition extends Condition<Iterable<String>> {
  private Collection<String> collection;

  public ContainsCondition(Iterable<String> values) {
    super("contains " + values);
    this.collection = newArrayList(values);
  }

  static ContainsCondition contains(Collection<String> set) {
    return new ContainsCondition(set);
  }

  @Override
  public boolean matches(Iterable<String> actual) {
    Collection<String> values = newArrayList(actual);
    for (String string : collection) {
      if (!values.contains(string)) return false;
    }
    return true;
  };
}

It might not be what you if you expect that the presence of your tags in one collection implies they are not in the other one.

like image 164
Joel Costigliola Avatar answered Sep 23 '22 18:09

Joel Costigliola