37

In my test case, I get an integer value:

int val = getXXX();

Then, I would like to check if val either equals to 3 or equals to 5 which is OK in either case. So, I did:

assertTrue(val == 3 || val==5);

I run my test, the log shows val is 5, but my above assertion code failed with AssertionFailedError. Seems I can not use assertTrue(...) in this way, then, how to check true for OR condition?

double-beep
  • 5,031
  • 17
  • 33
  • 41
Leem.fin
  • 40,781
  • 83
  • 202
  • 354

5 Answers5

58

You can use Hamcrest matchers to get a clearer error message here:

int i = 2;
assertThat(i, Matchers.either(Matchers.is(3)).or(Matchers.is(5))

or

int i = 2;
assertThat(i, Matchers.anyOf(Matchers.is(3),Matchers.is(5)));

This will more clearly explain:

Expected: (is <3> or is <5>)
     but: was <2>

showing exactly the expectation and the incorrect value that was provided.

Katie
  • 45,622
  • 19
  • 93
  • 125
Joe
  • 29,416
  • 12
  • 68
  • 88
  • 4
    For this to work one has to include a dependency on hamcrest-library. JUnit only depends on hamcrest-core, which does not include the Matchers class. – toongeorges Feb 14 '17 at 14:45
  • 4
    Tor those who don't have `Matchers` class in the Hamcrest library, you can use `org.hamcrest.CoreMatchers` instead. The example from the answer is than in this form: `assertThat(i, CoreMatchers.either(CoreMatchers.is(3)).or(CoreMatchers.is(5))` – cgrim Feb 05 '19 at 12:55
28

ive tried to write quick test:

@Test
public void testName() {
    int i = 5;
    junit.framework.Assert.assertTrue(i == 3 || i == 5);

}

its passing always so i guess there is some inbetween code when your value is changed. You can use

org.junit.Assert.assertEquals(5, i);

to check value - this assertion will print out nice info whats wrong, for example:

java.lang.AssertionError: 
Expected :4
Actual   :5
smajlo
  • 972
  • 10
  • 21
5

While Harmcrest matchers can do the job, these constants can be easily refactored to a more meaninful constant, like a list of valid values. Then you can use the contains method to check that the value is present in the list - IMO is also easier to read:

public class Foo {
    public static final List<Integer> VALID_VALUES = Arrays.asList(3, 5);
}

@Test
public void testName() {
    int i = 5;
    Assert.assertTrue(Foo.VALID_VALUES.contains(i));
}
A. Rodas
  • 20,171
  • 8
  • 62
  • 72
  • You would need to define a constant for each test case; I don't think this is reasonable beyond a couple of test cases. These constants will potentially be far from the place they're used. Another readability problem: `Foo.VALID_VALUES.contains(i)` is less clear than the approach with Harmcrest matchers. Harmcrest also provides a matcher with contains, which would also be much better than this. – garci560 Aug 30 '17 at 10:55
  • 3
    The Hamcrest version is a lot better because it will print the observed value on failure. There is nothing more annoying than getting a test failure back from a long CI build which just says "false was not true". – Rich Jul 19 '19 at 10:19
2

In my case I wanted to do some complex assertion logic, so I simply implemented a method that returns a boolean and it did the job, the way it would be implemented in this example is as follows:

private Boolean is3or5(Integer val) {
    if(val == 3 || val == 5) {
        return true;
    }
    return false;
}

Then do the assertion:

assertTrue(is3or5(val));

Of course the method can contain more complex logic if needed

Mohamed Ibrahim Elsayed
  • 2,734
  • 3
  • 23
  • 43
0

with TestNG this is also possible

Assert.assertTrue(val == 3 || val==5)
Adrian Jimenez
  • 979
  • 9
  • 23