ThomasThiebaud
ThomasThiebaud

Reputation: 11969

Should I assert or throw an exception in a junit library?

I'm writting a java library to easily write some junit tests. I don't know if I must assert inside my library or throw an exception. Here is an example. Asuming I define, in my library, this function to check the number of methods of class

public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods) {
     int numberOfMethods = clazz.getDeclaredMethods().length;
     //TODO compare number and expected number
}

Should I

  1. Directly assert inside my library

    Assert.assertTrue(expectedNumberofMethod > 0); 
    Assert.assertEquals(numberOfMethods,expectedNumberOfMethods);
    //...
    
  2. Throw an exception an let the user handle this exception. Since this library is designed to be used in unit tests, the user will be able to catch some of this exception using @Test(expected=SomeCustomException.class)

    public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods)  throws IllegalArgumentException, SomeCustomException {
        if(expectedNumberOfMethods <= 0)
            throw new IllegalArgumentException(/*...*/);
    
        int numberOfMethods = clazz.getDeclaredMethods().length;
    
        if(numberOfMethods != expectedNumberOfMethods)
            throw new SomeCustomException(/*...*/);
    }
    

EDIT This is a dummy example

Upvotes: 1

Views: 417

Answers (4)

Michael Lloyd Lee mlk
Michael Lloyd Lee mlk

Reputation: 14661

expectedNumberofMethod > 0 should be an IllegalArgumentException. The test has not failed, the method has been called incorrectly.

numberOfMethods == expectedNumberOfMethods should throw a java.lang.AssertionError (or a like), how you do this is up to you, you could use Assert.assertThat, but it binds you to a test framework. You could throw it directly, but you have to do more manual work.

If you use Assert.assertThat, remember that the first argument can be a String description of what went wrong. Use it.

Don't use custom exceptions (that do not extent java.lang.AssertionError), think about what the users of your API will be expecting, and do that. Every other assert causes a java.lang.AssertionError to be throw, but you are doing something different.

Upvotes: 1

Eric Citaire
Eric Citaire

Reputation: 4513

You should throw a java.lang.AssertionError exception if an assertion is false.

Also, try not to re-invent the wheel, take a look at AssertJ which does exactly what you want.

// Example
assertThat(clazz.getDeclaredMethods()).hasSize(5);

Upvotes: 1

wero
wero

Reputation: 32980

Your are planning to create specialized assert methods, like as you would write an extension to the Assert class.

For this you should directly throw assert errors (variant 1), as the assert methods in Assertdo, providing a helpful error message.

The possibility to specify expected exceptions in the @Test annotation serves a different purpose. With this annotation Junit allows you to test that a piece of code throws an expected exception, without the need in the test code to catch the exception.

Upvotes: 4

Martin Hansen
Martin Hansen

Reputation: 2101

I would use the junit fail() method that is used in pretty much all other assert methods in the junit library

public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods) {
    int numberOfMethods = clazz.getDeclaredMethods().length;
    if (numberOfMethods != expectedNumberOfMethods) {
        fail("some failing message);
    }
}

Upvotes: 2

Related Questions