21

This seems like a super simple question, but I just cannot figure it out.

I'm just trying to assert that a string is equal to "string1" OR "string2".

Here's what I've tried, but neither obviously doesn't work.

assertEquals(d.getFormType(), "string1") || assertEquals(d.getFormType(), "string2");

assertEquals(d.getFormType(), "string1" || "string2");
Catfish
  • 18,876
  • 54
  • 209
  • 353

6 Answers6

32

I recommend you use Hamcrest matchers. They are integrated into JUnit via assertThat(), but you'll need to download and install hamcrest-all.jar too.

Using Hamcrest, you could solve your problem like this:

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

assertThat(d.getFormType(), isOneOf("string1", "string2"));

Another alternative, if you can't install Hamcrest, would be to use a regular expression:

assertTrue(d.getFormType().matches("(string1|string2)"));

This is shorter, and arguably more readable, than combining two equals() statements:

String actual = d.getFormType();
assertTrue("string1".equals(actual) || "string2".equals(actual));
ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
  • I was hoping someone would post an example of the Matchers. I looked at this but couldn't figure it out. – Catfish Oct 04 '12 at 14:24
  • Yeah they work really well and give good diagnostic messages when they don't match. – ᴇʟᴇvᴀтᴇ Oct 04 '12 at 14:26
  • When trying to import org.hamcrest.Matchers.*, it can't be resolved and therefore isOneOf doesn't work. I'm using junit 4.10 – Catfish Oct 04 '12 at 14:31
  • 1
    Sorry, you'll need to download and install the Hamcrest jar separately. JUnit ships with the barest outline of Hamcrest - only enough to support integration. – ᴇʟᴇvᴀтᴇ Oct 04 '12 at 14:33
  • Ok gotcha. Thanks for the tip. – Catfish Oct 04 '12 at 14:35
  • Just so I can try to improve my future answers, what prompted you to accept hmjd's response over mine? – ᴇʟᴇvᴀтᴇ Oct 04 '12 at 14:39
  • It was a tough decision to decide who to give the checkmark to, but i chose his because i used the method where i could specify a message. Your answer was my second choice as i liked the alternative ways of doing things that you displayed. I upvoted both of you though. – Catfish Oct 04 '12 at 14:44
  • Funny because with Hamcrest, you don't *need* to specify a message. It automagically produces good messages. – ᴇʟᴇvᴀтᴇ Oct 04 '12 at 14:47
  • I didn't use hamcrest because I didn't want to bother with adding another jar. No hard feelings. – Catfish Oct 04 '12 at 14:49
22

You could use assertTrue():

assertTrue(d.getFormType().equals("string1") ||
           d.getFormType().equals("string2"));

or use the extended version to provide more information in the event of failure:

assertTrue("Unexpected value for d.getFormType(): " + d.getFormType(),
           d.getFormType().equals("string1") ||
           d.getFormType().equals("string2"));
hmjd
  • 120,187
  • 20
  • 207
  • 252
  • The second code is prone to NPEs and since the method always returns one of two possible values, the message could contain a different string than was tested. – Aaron Digulla Oct 04 '12 at 14:44
  • @AaronDigulla, see the accepted answer to this question regarding NPEs: http://stackoverflow.com/questions/9888508/string-equals-argument-ordering. As for argument value changing this is a guess on your part. The method appears to be a query method and should return the same value no matter how often it is called (without any intervening object modification methods being invoked, which is not the case here). – hmjd Oct 04 '12 at 14:47
  • 1
    The problem with early NPE is that it often leaves you with an error in a long line of code and no clue which of the 50 places caused the NPE. Here, the `assertTrue()` would tell you that `result` is null if it would get that far. – Aaron Digulla Oct 04 '12 at 14:53
  • 2
    Hamcrest is much better for this, as the assertion is short and readable, and provides diagnostics in case of failure. See the answer from @aetheria. – Kkkev Oct 05 '12 at 06:13
  • This has the disadvantage that if the condition fails, you will not see the cause. You will only see that the condition was false. – Richard Jessop Nov 07 '21 at 00:39
4

The assertion class doesn't have a direct way to do what you want. But you can always fall back to assertTrue and check any condition you want.

assertTrue("string1".equals(d.getFormType()) || "string2".equals(d.getFormType()))
Martin Serrano
  • 3,727
  • 1
  • 35
  • 48
1

how about

Assert.assertTrue("msg", Arrays.asList("string1", "string2").contains(searchString));

I would update msg to be a nice friendly message if it fails.

RNJ
  • 15,272
  • 18
  • 86
  • 131
0

I don't know of an exact JUnit style of doing this, but I would do something simpler that will work:

boolean stringEquals = false;
if ("string1".equals(d.getFormType()) || "string2".equals(d.getFormType())) {
    stringEquals = true;
}
assertTrue(stringEquals);
Dan W
  • 5,718
  • 4
  • 33
  • 44
0

Your question doesn't make sense. Unit tests always have the same result - they aren't random or rather, they shouldn't be. That's why JUnit doesn't support alternating results.

Try to find a way to setup the test in such a way that the output doesn't change.

If that's really impossible there is probably something wrong with your code or at least its design.

Try to fix this.

If you really can't, then you can use:

boolean valid = ....some complex check...
assertTrue( valid );

[EDIT] To test several values at once, you can use this trick:

String[] values = ...;
assertEquals( "0:...\n1:...",  "0:" + values[0] + "\n" + "1:" + values[1] ... );

i.e. you put all the values into a long string and then check the whole string. Most IDEs will display the differences in two text editors side by side so any mismatch will be easy to see + the little hints (0:, ...) in the text will tell you exactly where the error is.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • I want to test this output because I'm passing in a comma separated string and splitting it by the comma. I want to test that my method can handle a comma separated string correctly. – Catfish Oct 04 '12 at 14:21
  • Then, it makes even less sense. It should always return the same value(s). What you need is `and` instead of `or`. See my edits. – Aaron Digulla Oct 04 '12 at 14:36
  • No you're wrong. I'm setting a string `string1,string2`. In my method i split apart that string and run a search for both `string1`, and `string2` and then put the results together and return them. So i want to verify via my junit test that the form type is either string1, or string2. Make sense? – Catfish Oct 04 '12 at 14:39
  • 1
    No. This smells like an integration test: you're testing too much. Try to split the method into smaller parts so you can test the "split comma separated values" independently of the rest. – Aaron Digulla Oct 04 '12 at 14:41