Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capturing calls to org.junit.jupiter.api.assertThrows<MyCustomException> #1165

Open
vincent-fuchs opened this issue Sep 8, 2023 · 2 comments

Comments

@vincent-fuchs
Copy link
Contributor

hi,

in my Kotlin code base, I have quite a lot of calls to org.junit.jupiter.api.assertThrows<MyCustomException> , and depending on the package, I want to block it or not.

I am a bit stuck on how to capture the exception type in an ArchUnit condition...

so far, I am able to identify the places where assertThrows is called, but what other predicate can I use to filter on the exception type ?

        val callOfAssertThrowsMyCustomException = callMethodWhere(
                target(name("assertThrows"))
         //then what ?
        )

is it even possible ? I have a doubt because when I try a different approach in debug mode, I am able to find the codeUnit I am interested in, but what I see is not reassuring :

image

we see that the exception "real" class doesn't seem to be available, it's just a Class.

If a more precise type information is not available to ArchUnit, it's going to be difficult, right ?

@hankem
Copy link
Member

hankem commented Sep 9, 2023

You're right; the generic type of org.junit.jupiter.api.Assertions.assertThrows does not show up in the byte code.
ArchUnit therefore cannot directly distinguish assertThrows<MyCustomException> from assertThrows<AnyOtherException>.

@hankem
Copy link
Member

hankem commented Sep 9, 2023

I wonder whether testing for class objects referenced from the same test method (it's not possible to attribute them directly to a method call) could be a useful workaround – even though this will have false positives and negatives.

This:

ArchRule rule = noClasses().should().callMethodWhere(
        target(name("assertThrows")).and(describe("", call ->
                call.getOwner().getReferencedClassObjects().stream()
                        .map(ReferencedClassObject::getRawType)
                        .anyMatch(javaClass -> javaClass.isEquivalentTo(NullPointerException.class))
        ))
);

is able to distinguish those:

@Test void test1() {
    assertThrows(NullPointerException.class, () -> requireNonNull(null));
}

@Test void test2() {
    assertThrows(IllegalArgumentException.class, () -> checkArgument(false));
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants