JUnit right way of test expected exceptions - java

Hello guys I was wondering if this way of testing my exception is ok, i have this exception i need to throw in the second test annotation, im receiving as result a red evil bar, and a succeed and a failure, as you can guess the failure is my concern, i have a fail(); there but the reason is because i read thats the way to test the exception and now im confused.
Also i have to say im willin get the green bar because im expecting the exception, but i dont know if failure is the right way to see the answer of the expected exception.
Also if you had any advice, I would appreciate it
#Before
public void setUp() throws Exception {
LogPack.logPacConfig(Constants.LOGGING_FILE);
gtfri = "+RESP:GTFRI,380502,869606020101881,INCOFER-gv65,,10,1,1,0.0,0,888.1,-84.194560,9.955602,20170220074514,,,,,,0.0,,,,100,210100,,,,20170220074517,40A2$";
weirdProtocol = "+RESP:GRI,380502,869606020101881,INCOFER-gv65,,10,1,1,0.0,0,888.1,-84.194560,9.955602,20170220074514,,,,,,0.0,,,,100,210100,,,,20170220074517,40A2$";
factory = new LocomotiveFactory();
}
#Test
public void GTFRICreationTester_shouldPass() throws TramaConProtolocoloDesconocido {
assertTrue(factory.createLocomotive(gtfri, false, new Date()) instanceof LocomotiveGTFRI);
}
#Test(expected = TramaConProtolocoloDesconocido.class)
public void GTFRICreationTester_shouldFail() {
try {
factory.createLocomotive(weirdProtocol, false, new Date());
fail("Expected an TramaConProtolocoloDesconocido");
} catch (TramaConProtolocoloDesconocido e) {
//assertSame("exception thrown as expected", "no se conoce el protocolo dado para la creacion de este factory", e.getMessage());;
}
}

There is 3 most common ways to test expected exception:
First one is the most common way, but you can test only the type of expected exception with it. This test will fail if ExceptionType won't be thrown:
#Test(expected = ExceptionType.class)
public void testSomething(){
sut.doSomething();
}
Also you cannot specify the failure message using this approach
The better option is to use ExpectedException JUnit #Rule. Here you can assert much more for expected exception
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testSomething(){
thrown.expect(ExceptionType.class);
thrown.expectMessage("Error message");
thrown.expectCause(is(new CauseOfExeption()));
thrown.reportMissingExceptionWithMessage("Exception expected");
//any other expectations
sut.doSomething();
}
The third option will allow you to do the same as with using ExpectedException #Rule, but all the assertion should be written manually. However the advantage of this method is that you can use any custom assertion and any assertion library that you want:
#Test
public void testSomething(){
try{
sut.doSomething();
fail("Expected exception");
} catch(ExceptionType e) {
//assert ExceptionType e
}
}

You can use ExpectedException which can provide you more precise information about the exception expected to be thrown with the ability to verify error message, as follows:
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
public class TestClass {
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Test
public void GTFRICreationTester_shouldFail() {
expectedException.expect(TramaConProtolocoloDesconocido.class);
factory.createLocomotive(weirdProtocol, false, new Date());
}
}
To expolore more about it, you can refer to the blog written by me here - Expected Exception Rule and Mocking Static Methods – JUnit

if your are using java 8, I would recommend to go for the AssertJ library
public void GTFRICreationTester_shouldFail() {
assertThatExceptionOfType(EXCEPTION_CLASS).isThrownBy(() -> { factory.createLocomotive(weirdProtocol, false, new Date()) })
.withMessage("MESSAGE")
.withMessageContaining("MESSAGE_CONTAINING")
.withNoCause();
}
with that solution you can at one verify exception type, with message etc.
for more reading, take a look at:
http://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html#exception-assertion

You don't need to catch the Exception with try-catch
#Test(expected = TramaConProtolocoloDesconocido.class)
public void GTFRICreationTester_shouldFail() {
factory.createLocomotive(weirdProtocol, false, new Date());
}
If we suppose that factory.createLocomotive(weirdProtocol, false, new Date()) throws the exception when you apply a scenario that makes the exception thrown.
void createLocomotive(param...) {
//something...
throw new TramaConProtolocoloDesconocido();
}

Related

Junit Asserting failed HTTP post request

I have an HTTPClient test for my spring boot app. I have a class that throws an exception if the a POST request to the server is in a string 2048 bytes or over.
#Component
public class ApplicationRequestSizeLimitFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
System.out.println(request.getContentLength());
if (request.getContentLengthLong() >= 2048) {
throw new IOException("Request content exceeded limit of 2048 bytes");
}
filterChain.doFilter(request, response);
}
}
I created a unit test for it but I am not sure how I can write an assert statement to check if it fails to post the request.
Right now I have this so far in my test class
#Test
public void testSize() throws ClientProtocolException, IOException {
Random r = new Random(123);
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 65536; i++)
s += r.nextInt(2);
String result = Request.Post(mockAddress)
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(s, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
}
This test fails which is what I want but I want to create an assert so it passes (assert that it fails the http response due to being over the byte limit).
You can surround the failing part with a try/catch, and call fail() at the end of the try block. If an exception is thrown, the fail() instruction should not be reached, and your test should pass.
#Test has an argument to assert that a particular exception gets thrown, you could write your test like e.g :
#Test(expected = IOException.class)
public void testSize() throws ClientProtocolException, IOException {
...
}
There are 3 ways you can achieve that:
1) Use #Test(expected = ....) annotation where you provide class of exception you want to check.
#Test(expected = IOException.class)
public void test() {
//... your test logic
}
This is not a recommended way of exception testing unless your test is really really small and does one thing only. Otherwise, you may get an IOException thrown but you won't be sure which part of test code exactly caused it.
2) Use #Rule annotation with ExpectedException class:
#Rule
public ExpectedException exceptionRule = ExpectedException.none();
#Test
public void testExpectedException() {
exceptionRule.expect(IOException.class);
exceptionRule.expectMessage("Request too big.");
//... rest of your test logic here
}
Please note that exceptionRule has to be public.
3) And last one, quite old-fashioned way:
#Test
public void test() {
try {
// your test logic
fail(); // if we get to that point it means that exception was not thrown, therefore test should fail.
} catch (IOException e) {
// if we get here, test is successfull and code seems to be ok.
}
}
It's an old fashioned way that adds some unnecessary code to your test that is supposed to be clean.
There is another solution, not already presented in these answers, and is my personal preference. assertThatThrownBy
in your case
#Test
public void testSizeException(){
assertThatThrownBy(()-> Request.Post(mockAddress)
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(s, ContentType.TEXT_PLAIN)
.execute().returnContent().asString())
.isInstanceOf(IOException.class)
.hasMessageContaining("Request content exceeded limit of 2048
bytes");
}
*Disclaimer, above code written directly into SO editor

How do you assert that an exception is thrown if it has already been consumed/handled/caught

Let's say I test a class method that is reliant on another method that we do not want or can not test directly, which handles a checked exception, in the following manner:
public class A {
public void process(){
if (isProcessingSuccessful()){
LOG.info("Success");
}
else {
LOG.error("Fail");
}
}
private boolean isProcessingSuccessful(){
try{
doSomeOtherStuff();
return true;
}
catch (Exception e){
return false;
}
}
}
Now, if I have a test class testing for the A#process(), like:
#Test
public void shouldFailDueToCommandGatewayError() {
A a = new A();
// setting up preconditions
//testing here
a.process();
//Now, assert exception was thrown during the course of a.process() execution, something like
exception.expect(NullPointerException.class);
// ?? how to do that?
}
TLTD: It is possible to write separate test for isProcessingSuccessful() or do something similar, but let's say that method is not accessible for testing, like it's private in a library?
Given the above constraints, is there any way to write a test in a way that ascertains the exception was thrown in the underlying method as above?
No, junit can't tell the exception was thrown, since it gets eaten by the code being tested. For you to detect what happened here you would have to check what was written to the log. Replace the appender with something that holds onto what is written to it, then the test can verify what was written to it at the end of the test.
You can't catch the exception again which have been already consumed. The only way is to catch the exception with the test method as described below.
Annote the test method that is supposed to fail with #Test and use the expected parameter for the expected exception.
#Test(expected = NullPointerException.class)
public void shouldFailDueToCommandGatewayError() {
// something that throws NullPointerException
}
#Test(expected = NullPointerException.class)
This basically says:
If this test quits with a NullPointerException then everything is as expected. Otherwise this test will fail.
#Test(expected = NullPointerException.class)
has been mentioned already. This feature came wuth JUnit 4. Before that and if you want to do want to check more than just a particular type of exception being thrown, you can do something like this:
try {
doSometing("", "");
fail("exception expected");
}
catch(IllegalArgumentException iae) {
assertEquals("check message", "parameter a must not be empty", iae.getMessage());
assertNull("check non-existance of cause", iae.getCause());
}
try {
doSometing("someval", "");
fail("exception expected");
}
catch(IllegalArgumentException iae) {
assertEquals("check message", "parameter b must not be empty", iae.getMessage());
assertNull("check non-existance of cause", iae.getCause());
}
This is particular useful if the same type of exception is thrown and you want to ensure that the "correct" exception is thrown with a given combination of parameters.

How to check multiple exceptions with one JUnit Method?

i have this code in my program which is needed to be tested with jUnit
void deleteCustomer(String name) throws UnknownCustomerException,
AccountNotEmptyException {
if (name == null) {
throw new NullPointerException();
} else if (!exists(name)) {
throw new UnknownCustomerException();
} else if (getCustomer(name).deletable()) {
customerList.remove(getCustomer(name));
}
}
I thought i can test it in one JUnit method like
#Test
public void createCustomer(){
System.out.println("createCustomerTest");
try {
element.createCustomer(null);
//fail("Expected an IndexOutOfBoundsException to be thrown");
} catch (NullPointerException anIndexOutOfBoundsException) {
assertTrue(anIndexOutOfBoundsException.getMessage().equals("NullPointerException"));
}
}
As you can see I already tried unsuccessfully to implement the NPE.
How can I check for several Exceptions in one JUnit Method? I checked some How-To's in the web but failed with that too.
I think in your case you should have separate tests, however you can achieve this like so if using Java 8:
Using an AssertJ 3 assertion, which can be used alongside JUnit:
import static org.assertj.core.api.Assertions.*;
#Test
public void test() {
Element element = new Element();
assertThatThrownBy(() -> element.createCustomer(null))
.isInstanceOf(NullPointerException.class)
.hasMessageContaining("NullPointerException");
assertThatThrownBy(() -> element.get(1))
.isInstanceOf(IndexOutOfBoundsException.class);
}
It's better than #Test(expected=IndexOutOfBoundsException.class) or .expect syntax because it guarantees the expected line in the test threw the exception and lets you check more details about the exception, such as message.
Maven/Gradle instructions here.
Write for each exception its own test. It will be only one thrown at a time anyway.
For example a simplified method:
void deleteCustomer( String name ) throws UnknownCustomerException
{
if ( name == null )
{
throw new NullPointerException();
}
else if ( !exists( name ) )
{
throw new UnknownCustomerException();
}
}
You have then two tests that each check if its exception is thrown:
#Test( expected = NullPointerException.class )
public void deleteCustomer_shouldThrowNullpointerIfNameIsNull() throws UnknownCustomerException
{
String name = null;
cut.deleteCustomer( name );
}
#Test( expected = UnknownCustomerException.class )
public void deleteCustomer_shouldThrowUnknownCustomerExceptionIfNameIsUnknown() throws UnknownCustomerException
{
String name = "someUnknownName";
cut.deleteCustomer( name );
}
The problem with the NullpointerException is, that the test is true/successful/green if the NPE is thrown anywhere in the method - so you should make sure, that that is not happening for the test to be meaningful.
You could add several "catch" statement into the test method for different exceptions, like:
try {
element.createCustomer(null);
Assert.fail("Exception was expected!");
} catch (NullPointerException _ignore) {
} catch (UnknownCustomerException _ignore) {
}
or with Java 87
try {
element.createCustomer(null);
Assert.fail("Exception was expected!");
} catch (NullPointerException | UnknownCustomerException _ignore) {
}
But if you switch from JUnit to TestNG, then your test will be much cleaner:
#org.testng.annotations.Test(expectedExceptions = { NullPointerException.class, UnknownCustomerException.class })
public void createCustomer() throws NullPointerException, UnknownCustomerException {
element.createCustomer(null);
}
More information about "expectedException" is here: http://testng.org/doc/documentation-main.html and example of the usage can be found here: http://www.mkyong.com/unittest/testng-tutorial-2-expected-exception-test/
I suggest that you take a closer look at the JavaDoc of ExpectedException and implement different tests for different validations, e.g.
public class CustomerTest {
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void throwsNullPointerExceptionForNullArg() {
exception.expect(NullPointerException.class);
element.createCustomer(null);
}
#Test
public void throwsUnknwonCustomerExceptionForUnkownCustomer() {
exception.expect(UnknownCustomerException.class);
// exception.expectMessage("Some exception message"); uncomment to verify exception message
element.createCustomer("unknownCustomerName");
}
#Test
public void doesNotThrowExceptionForKnownCustomer() {
element.createCustomer("a known customer");
// this test pass since ExpectedException.none() defaults to no exception
}
}

Checking for 2 expected values in Junit

I have a java program which throws an exception with 2 different messages for 2 different scenarios and I want the Junit test case to check for equality for both of these messages. As an example -
public void amethod() {
// do some processing
if(scenario1 == true) {
throw new MySystemException("An error occured due to case 1 being incorrect.");
}
else if(scenario2 == true) {
throw new MySystemException("An error occured as case 2 could not be found");
}
}
Now the JUnit for this would be something like-
public void testAMethod() {
// do something
assertEquals("Expected", "Actual");
}
As I understand, in this above example, if I use the Scenario1 exception message the junit will fail when an exception is thrown for Scenario2 and vice versa.
I would like to know if there is any other way provided in Junit by which I can use this one test method and check for both the messages for the test to pass?
Something like an OR, if possible to provide the "Expected" value with both these expected message.
I hope my query is clear enough.
Thanks
UPDATE
Sorry for the delayed response, had got caught up with some other urgent matter.
Thank you all for the very nice suggestions, it certainly has helped me to understand a bit better now.
Eventually, to keep it rather simple I decided to implement a somewhat similar solution suggested by Don Roby. So created a new test class which looks like -
public void testAMethodScenario1() {
// do the necessary
assertEquals("Expected Exception Message 1", "Actual");
}
public void testAMethodScenario2() {
// do the necessary
assertEquals("Expected Exception Message 2", "Actual");
}
Thank you all again for your responses.
I think you need to manually catch the exception (for each scenario) and individually check the message:
try {
// trigger scenario 1
fail("An exception should have been thrown here !");
} catch (MySystemException e1) {
assertEquals("Wrong error message", m1, e1.getMessage());
}
try {
// trigger scenario 2
fail("An exception should have been thrown here !");
} catch (MySystemException e2) {
assertEquals("Wrong error message", m2, e2.getMessage());
}
Of course, you can have these scenarios defined as enum constants and simply iterate through them and check each of them within a loop, since the "copy/paste design pattern" is pretty obvious in the above code. :)
You seem to be asking two things here, how to test an exception and how to assert that a value matches either of two possible expected values.
To test for an exception, you can either use a JUnit4 annotation:
#Test(expected=MySystemException.class)
public void testException() {
amethod();
}
or use a try-catch in your test:
#Test
public void testException() {
try {
amethod();
fail("MySystemException expected");
}
catch (MySystemException e) {
// Success!
}
}
And if you have only one message, in the try-catch version you can assert that you got it with an AssertEquals in the catch block.
The best testing would have separate tests for your two scenarios, and expect the correct single message. Better code might in fact have distinct exceptions for the two situations.
But the need for a more complex assertion than simple equality does come up anyway, and there's an elegant solution for it in Hamcrest matchers.
Using that for this situation, you could write something like (untested - don't trust my syntax completely):
#Test
public void testException() {
try {
amethod();
fail("MySystemException expected");
}
catch (MySystemException e) {
String expectedMessage1 = "An error occured due to case 1 being incorrect.";
String expectedMessage2 = "An error occured as case 2 could not be found";
assertThat(e.getMessage(),
anyOf(equalTo(expectedMessage1), equalTo(expectedMessage2)));
}
}
Can you predict which scenario will occur? If so, Costi's answer is correct. If not, because there's some randomness or whatever, you can write:
#Test
public void testAmethodThrowsException() {
try {
amethod();
fail("amethod() should have thrown an exception");
}
catch (MySystemException e) {
String msg = e.getMessage();
assertTrue("bad message: " + msg, msg.equals("An error occured due to case 1 being incorrect.") || msg.equals("An error occured as case 2 could not be found"));
}
}
The declared types of exception thrown bya method are part of its API. If you really want to distinguish different failure modes, you should declare a different exception type for each failure mode.
So, something like this:
/**
* Do something.
* #throws MySystemException1 in case 1.
* #throws MySystemException2 if Foo not found.
*/
public void amethod() {
// do some processing
if(scenario1 == true) {
throw new MySystemException1("Case 1.");
}
else if(scenario2 == true) {
throw new MySystemException2("Foo not found");
}
}
#Rule solution in JUnit4:
public class ExceptionRule implements MethodRule {
#Override
public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
Assert.fail();
} catch (MySystemException e) {
if(scenario1)
assertEquals("Expected error message1", e1.getMessage();
if(scenario2)
assertEquals("Expected error message2",e1.getMessage();
}
}
};
}
}
In your testcase, use the Rule:
#Rule public ExceptionRule rule = new ExceptionRule();
JUnit 4 provides (Expected Exception.class)
#Test(expected= MySystemException.class) public void empty() {
// what ever you want
}
Google: Expected Exceptions JUnit for more info.
BDD Style Solution with Catch Exception
#Test
public void testAMethodScenario1() {
//given scenario 1
when(foo).amethod();
then(caughtException())
.isInstanceOf(MySystemException.class)
.hasMessage("An error occured due to case 1 being incorrect.");
}
#Test
public void testAMethodScenario2() {
//given scenario 2
when(foo).amethod();
then(caughtException())
.isInstanceOf(MySystemException.class)
.hasMessage("An error occured as case 2 could not be found");
}
Source code
https://gist.github.com/mariuszs/7490875
Dependencies
com.googlecode.catch-exception:catch-exception:1.2.0
A better solution with #Rule, you can assert both exception and expection message as well.
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Test
public void aMethod_Scenario1True_ThrowsException() {
expectedException.expect(MySystemException.class);
expectedExcepion.expectMessage("An error occured due to case 1 being incorrect.");
//when().thenReturn();
//handle the repositories, static methods and other sub methods, if needed
amethod();
}
#Rule is the more elegant way to write the exception.

How do I assert my exception message with JUnit Test annotation?

I have written a few JUnit tests with #Test annotation. If my test method throws a checked exception and if I want to assert the message along with the exception, is there a way to do so with JUnit #Test annotation? AFAIK, JUnit 4.7 doesn't provide this feature but does any future versions provide it? I know in .NET you can assert the message and the exception class. Looking for similar feature in the Java world.
This is what I want:
#Test (expected = RuntimeException.class, message = "Employee ID is null")
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() {}
You could use the #Rule annotation with ExpectedException, like this:
#Rule
public ExpectedException expectedEx = ExpectedException.none();
#Test
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() throws Exception {
expectedEx.expect(RuntimeException.class);
expectedEx.expectMessage("Employee ID is null");
// do something that should throw the exception...
System.out.println("=======Starting Exception process=======");
throw new NullPointerException("Employee ID is null");
}
Note that the example in the ExpectedException docs is (currently) wrong - there's no public constructor, so you have to use ExpectedException.none().
In JUnit 4.13 you can do:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
...
#Test
void exceptionTesting() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> { throw new IllegalArgumentException("a message"); }
);
assertEquals("a message", exception.getMessage());
}
This also works in JUnit 5 but with different imports:
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
...
I like the #Rule answer. However, if for some reason you don't want to use rules. There is a third option.
#Test (expected = RuntimeException.class)
public void myTestMethod()
{
try
{
//Run exception throwing operation here
}
catch(RuntimeException re)
{
String message = "Employee ID is null";
assertEquals(message, re.getMessage());
throw re;
}
fail("Employee Id Null exception did not throw!");
}
Do you have to use #Test(expected=SomeException.class)? When we have to assert the actual message of the exception, this is what we do.
#Test
public void myTestMethod()
{
try
{
final Integer employeeId = null;
new Employee(employeeId);
fail("Should have thrown SomeException but did not!");
}
catch( final SomeException e )
{
final String msg = "Employee ID is null";
assertEquals(msg, e.getMessage());
}
}
Actually, the best usage is with try/catch. Why? Because you can control the place where you expect the exception.
Consider this example:
#Test (expected = RuntimeException.class)
public void someTest() {
// test preparation
// actual test
}
What if one day the code is modified and test preparation will throw a RuntimeException? In that case actual test is not even tested and even if it doesn't throw any exception the test will pass.
That is why it is much better to use try/catch than to rely on the annotation.
I never liked the way of asserting exceptions with Junit. If I use the "expected" in the annotation, seems from my point of view we're violating the "given, when, then" pattern because the "then" is placed at the top of the test definition.
Also, if we use "#Rule", we have to deal with so much boilerplate code. So, if you can install new libraries for your tests, I'd suggest to have a look to the AssertJ (that library now comes with SpringBoot)
Then a test which is not violating the "given/when/then" principles, and it is done using AssertJ to verify:
1 - The exception is what we're expecting.
2 - It has also an expected message
Will look like this:
#Test
void should_throwIllegalUse_when_idNotGiven() {
//when
final Throwable raisedException = catchThrowable(() -> getUserDAO.byId(null));
//then
assertThat(raisedException).isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Id to fetch is mandatory");
}
Raystorm had a good answer. I'm not a big fan of Rules either. I do something similar, except that I create the following utility class to help readability and usability, which is one of the big plus'es of annotations in the first place.
Add this utility class:
import org.junit.Assert;
public abstract class ExpectedRuntimeExceptionAsserter {
private String expectedExceptionMessage;
public ExpectedRuntimeExceptionAsserter(String expectedExceptionMessage) {
this.expectedExceptionMessage = expectedExceptionMessage;
}
public final void run(){
try{
expectException();
Assert.fail(String.format("Expected a RuntimeException '%s'", expectedExceptionMessage));
} catch (RuntimeException e){
Assert.assertEquals("RuntimeException caught, but unexpected message", expectedExceptionMessage, e.getMessage());
}
}
protected abstract void expectException();
}
Then for my unit test, all I need is this code:
#Test
public void verifyAnonymousUserCantAccessPrivilegedResourceTest(){
new ExpectedRuntimeExceptionAsserter("anonymous user can't access privileged resource"){
#Override
protected void expectException() {
throw new RuntimeException("anonymous user can't access privileged resource");
}
}.run(); //passes test; expected exception is caught, and this #Test returns normally as "Passed"
}
If using #Rule, the exception set is applied to all the test methods in the Test class.
I would prefer AssertJ for this.
assertThatExceptionOfType(ExpectedException.class)
.isThrownBy(() -> {
// method call
}).withMessage("My message");
I like user64141's answer but found that it could be more generalized. Here's my take:
public abstract class ExpectedThrowableAsserter implements Runnable {
private final Class<? extends Throwable> throwableClass;
private final String expectedExceptionMessage;
protected ExpectedThrowableAsserter(Class<? extends Throwable> throwableClass, String expectedExceptionMessage) {
this.throwableClass = throwableClass;
this.expectedExceptionMessage = expectedExceptionMessage;
}
public final void run() {
try {
expectException();
} catch (Throwable e) {
assertTrue(String.format("Caught unexpected %s", e.getClass().getSimpleName()), throwableClass.isInstance(e));
assertEquals(String.format("%s caught, but unexpected message", throwableClass.getSimpleName()), expectedExceptionMessage, e.getMessage());
return;
}
fail(String.format("Expected %s, but no exception was thrown.", throwableClass.getSimpleName()));
}
protected abstract void expectException();
}
Note that leaving the "fail" statement within the try block causes the related assertion exception to be caught; using return within the catch statement prevents this.
Import the catch-exception library, and use that. It's much cleaner than the ExpectedException rule or a try-catch.
Example form their docs:
import static com.googlecode.catchexception.CatchException.*;
import static com.googlecode.catchexception.apis.CatchExceptionHamcrestMatchers.*;
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
catchException(myList).get(1);
// then: we expect an IndexOutOfBoundsException with message "Index: 1, Size: 0"
assertThat(caughtException(),
allOf(
instanceOf(IndexOutOfBoundsException.class),
hasMessage("Index: 1, Size: 0"),
hasNoCause()
)
);
#Test (expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "This is not allowed")
public void testInvalidValidation() throws Exception{
//test code
}

Categories

Resources