ExpectedException cause of the cause?
Asked Answered
S

3

8

I'm trying to verify that all my exceptions are correct. Because values are wrapped in CompletableFutures, the exception thrown is ExecutionException with cause being the exception that I would normally check. Quick example:

void foo() throws A {
  try {
    bar();
  } catch B b {
    throw new A(b);
  }
}

So foo() translates exception thrown by bar(), and all of that is done inside CompletableFutures and AsyncHandlers (I won't copy the whole code, it's just for reference)

In my unit tests I'm making bar() throw an exception and want to check that it's translated correctly when calling foo():

Throwable b = B("bleh");
when(mock.bar()).thenThrow(b);
ExpectedException thrown = ExpectedException.none();
thrown.expect(ExecutionException.class);
thrown.expectCause(Matchers.allOf(
                instanceOf(A.class),
                having(on(A.class).getMessage(),
                        CoreMatchers.is("some message here")),
        ));

So far so good, but I also want to verify that cause of exception A is exception B and having(on(A.class).getCause(), CoreMatchers.is(b)) causes CodeGenerationException --> StackOverflowError

TL;DR: How do I get cause of cause of expected exception?

Striking answered 25/11, 2016 at 16:18 Comment(3)
Maybe this question is what you want (I'm not sure): #871716Maladminister
@RC. Almost, but I must go one level deeper and get the next cause :)Striking
You should be able to adapt: https://mcmap.net/q/344571/-junit-possible-to-39-expect-39-a-wrapped-exceptionMaladminister
M
4

Maybe you should try with the simple hasProperty Matcher, in order to isolate the problem:

thrown.expectCause(allOf(
                    instanceOf(A.class),
                    hasProperty("message", is("some message here")),
        ));
Mildamilde answered 26/11, 2016 at 17:28 Comment(0)
C
0

This is an example I use to test only the causal class chain. References :


import static org.hamcrest.Matchers.contains;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class CausalClassChainTest {

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Test
    public void test() throws Exception {
        expectedException.expect(IOException.class);
        expectedException.expectCause(new CausalClassChainMather(Exception.class, RuntimeException.class));

        throw new IOException(new Exception(new RuntimeException()));
    }

    private static class CausalClassChainMather extends TypeSafeMatcher<Throwable> {

        private final Class<? extends Throwable>[] expectedClasses;
        private List<Class<? extends Throwable>> causualClasses;
        private Matcher<Iterable<? extends Class<? extends Throwable>>> matcher;

        public CausalClassChainMather(Class<? extends Throwable>... classes) {
            this.expectedClasses = classes;
        }

        @Override
        public void describeTo(Description description) {
            // copy of MatcherAssert.assertThat()
            description.appendText("")
                    .appendText("\nExpected: ")
                    .appendDescriptionOf(matcher)
                    .appendText("\n     but: ");
            matcher.describeMismatch(causualClasses, description);
        }

        @Override
        protected boolean matchesSafely(Throwable item) {

            List<Class<? extends Throwable>> causes = new ArrayList<Class<? extends Throwable>>();
            while (item != null) {
                causes.add(item.getClass());
                item = item.getCause();
            }
            causualClasses = Collections.unmodifiableList(causes);

            // ordered test
            matcher = contains(expectedClasses);
            return matcher.matches(causualClasses);
        }
    }

}
Circumstantiality answered 23/8, 2017 at 16:2 Comment(0)
S
0

Try sth like, to verify the cause of the cause:

    thrown.expectCause(allOf(
            isA(org.apache.kafka.common.errors.SerializationException.class),
            hasProperty("message", containsString("Error deserializing Avro message for id")),
            hasProperty("cause", allOf(
                    isA(org.apache.avro.AvroTypeException.class),
                    hasProperty("message", containsString("missing required field blabla"))
                    ))
            ));
Silicosis answered 18/7, 2018 at 12:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.