Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUnit4 fail() is here, but where is pass()?

Tags:

java

junit

There is a fail() method in JUnit4 library. I like it, but experiencing a lack of pass() method which is not present in the library. Why is it so?

I've found out that I can use assertTrue(true) instead but still looks unlogical.

@Test
 public void testSetterForeignWord(){
  try {
   card.setForeignWord("");
   fail();
  } catch (IncorrectArgumentForSetter ex){
  }

 // assertTrue(true);
 }
like image 792
Eugene Avatar asked Oct 27 '10 17:10

Eugene


People also ask

What is difference between junit4 and JUnit5?

Differences Between JUnit 4 and JUnit 5 Some other differences include: The minimum JDK for JUnit 4 was JDK 5, while JUnit 5 requires at least JDK 8. The @Before , @BeforeClass , @After , and @AfterClass annotations are now the more readable as the @BeforeEach , @BeforeAll , @AfterEach , and @AfterAll annotations.

What is the tear down () method called in JUnit?

concept tearDown() in category junit When it is time to execute your test, the framework invokes runBare() , which sets up your fixture, runs the test, and then tears down your fixture. Notice that by placing tearDown() in a finally block, this method is guaranteed to be called even if the test fails.

How do you use assertTrue in JUnit?

assertTrue() If you wish to pass the parameter value as True for a specific condition invoked in a method, then you can make use of the. JUnit assertTrue(). You can make use of JUnit assertTrue() in two practical scenarios. By passing condition as a boolean parameter used to assert in JUnit with the assertTrue method.


4 Answers

Call return statement anytime your test is finished and passed.

like image 52
Horcrux7 Avatar answered Sep 23 '22 20:09

Horcrux7


As long as the test doesn't throw an exception, it passes, unless your @Test annotation specifies an expected exception. I suppose a pass() could throw a special exception that JUnit always interprets as passing, so as to short circuit the test, but that would go against the usual design of tests (i.e. assume success and only fail if an assertion fails) and, if people got the idea that it was preferable to use pass(), it would significantly slow down a large suite of passing tests (due to the overhead of exception creation). Failing tests should not be the norm, so it's not a big deal if they have that overhead.

Note that your example could be rewritten like this:

@Test(expected=IncorrectArgumentForSetter.class) public void testSetterForeignWord("") throws Exception {   card.setForeignWord(""); } 

Also, you should favor the use of standard Java exceptions. Your IncorrectArgumentForSetter should probably be an IllegalArgumentException.

like image 39
ColinD Avatar answered Sep 21 '22 20:09

ColinD


I think this question needs an updated answer, since most of the answers here are fairly outdated.

Firstly to the OP's question:

I think its pretty well accepted that introducing the "expected excepetion" concept into JUnit was a bad move, since that exception could be raised anywhere, and it will pass the test. It works if your throwing (and asserting on) very domain specific exceptions, but I only throw those kinds of exceptions when I'm working on code that needs to be absolutely immaculate, --most APIS will simply throw the built in exceptions like IllegalArgumentException or IllegalStateException. If two calls your making could potentitally throw these exceptions, then the @ExpectedException annotation will green-bar your test even if its the wrong line that throws the exception!

For this situation I've written a class that I'm sure many others here have written, that's an assertThrows method:

public class Exceptions {
    private Exceptions(){}

    public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){
        try{
            actionThatShouldThrow.run();
            fail("expected action to throw " + expectedException.getSimpleName() + " but it did not.");
        }
        catch(Exception e){
            if ( ! expectedException.isInstance(e)) {
                throw e;
            }
        }
    }
}

this method simply returns if the exception is thrown, allowing you to do further assertions/verification in your test.

with java 8 syntax your test looks really nice. Below is one of the simpler tests on our model that uses the method:

@Test
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() {
    //setup
    AxisRange range = new AxisRange(0,100);

    //act
    Runnable act = () -> range.setLowerBound(200);

    //assert
    assertThrows(IllegalArgumentException.class, act);
}

these tests are a little wonky because the "act" step doesn't actually perform any action, but I think the meaning is still fairly clear.

there's also a tiny little library on maven called catch-exception that uses the mockito-style syntax to verify that exceptions get thrown. It looks pretty, but I'm not a fan of dynamic proxies. That said, there syntax is so slick it remains tempting:

// given: an empty list
List myList = new ArrayList();

// when: we try to get the first element of the list
// then: catch the exception if any is thrown 
catchException(myList).get(1);

// then: we expect an IndexOutOfBoundsException
assert caughtException() instanceof IndexOutOfBoundsException;

Lastly, for the situation that I ran into to get to this thread, there is a way to ignore tests if some conidition is met.

Right now I'm working on getting some DLLs called through a java native-library-loading-library called JNA, but our build server is in ubuntu. I like to try to drive this kind of development with JUnit tests --even though they're far from "units" at this point--. What I want to do is run the test if I'm on a local machine, but ignore the test if we're on ubuntu. JUnit 4 does have a provision for this, called Assume:

@Test
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException {
    //this line will cause the test to be branded as "ignored" when "isCircleCI" 
    //(the machine running ubuntu is running this test) is true.
    Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
    //an ignored test will typically result in some qualifier being put on the results, 
    //but will also not typically prevent a green-ton most platforms. 

    //setup
    URL url = DLLTestFixture.class.getResource("USERDLL.dll");
    String path = url.toURI().getPath();
    path = path.substring(0, path.lastIndexOf("/"));

    //act
    NativeLibrary.addSearchPath("USERDLL", path);
    Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);

    //assert
    assertThat(dll).isNotNull();
}
like image 36
Groostav Avatar answered Sep 20 '22 20:09

Groostav


I was looking for pass method for JUnit as well, so that I could short-circuit some tests that were not applicable in some scenarios (there are integration tests, rather than pure unit tests). So too bad it is not there.

Fortunately, there is a way to have a test ignored conditionally, which actually fits even better in my case using assumeTrue method:

Assume.assumeTrue(isTestApplicable);

So here the test will be executed only if isTestApplicable is true, otherwise test will be ignored.

like image 26
Sebastian K Avatar answered Sep 21 '22 20:09

Sebastian K