ArchUnit
ArchUnit copied to clipboard
Capturing calls to org.junit.jupiter.api.assertThrows<MyCustomException>
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 :
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 ?
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>
.
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));
}