Reputation: 3824
In my Junit Jupiter API 5.5 test, I am calling my method which internally makes a HTTP call to a remote service. Now the remote service can be down or behave incorrectly. I want to skip my test in case the remote service is not behaving expectedly.
@Test
void testMe() {
// do something
Result res1 = myObject.retrieveResults(params)
// assert something
Result res2 = myObject.retrieveResults(param2)
//asert on results
}
Result retrieveResults(Parameters param) {
// do something
// call to remote service
// if they do not give result throw CustomException()
// return Result
}
So basically in my test i would want to check if myObject.retrieveResult
is throwing CustomException then skip that test, otherwise evaluate normally.
Upvotes: 8
Views: 13309
Reputation: 1829
We have 2 different ways to accomplish this tasks in JUnit 5.
For demo purposes, I have created a basic class which sends a request to the url
that is passed as an argument to its call(String url)
method and
returns true
or false
depending on the request result.
The body of the method is irrelevant here.
Assumptions.assumeTrue()/assumeFalse()
methodsAssumptions
class provides us with two overloaded methods - assumeTrue
and assumeFalse
. The idea is that, if the assumption is wrong, the test will be skipped.
So, the test will be something like this.
@Test
void call1() {
Assumptions.assumeTrue(new EndpointChecker(), "Endpoint is not available");
Assertions.assertTrue(HttpCaller.call("https://www.google.com"));
}
Here is the code for EndpointChecker
class.
static class EndpointChecker implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
// check the endpoint here and return either true or false
return false;
}
}
When the test is run, the availability of the endpoint will be checked first, if it is up, then the test will run.
So, let's start with creating the annotation. It is pretty straightforward.
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(EndpointAvailabilityCondition.class)
public @interface SkipWhenEndpointUnavailable {
String uri();
}
And EndpointAvailabilityCondition
class. Even though, it looks big, overall logic is very simple.
import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation;
public class EndpointAvailabilityCondition implements ExecutionCondition {
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
final var optional = findAnnotation(context.getElement(), SkipWhenEndpointUnavailable.class);
if (optional.isPresent()) {
final SkipWhenEndpointUnavailable annotation = optional.get();
final String uri = annotation.uri();
// check connection here start
boolean result = false; // dummy value
// check connection here end
if (result) {
return ConditionEvaluationResult.enabled("Connection is up");
} else {
return ConditionEvaluationResult.disabled("Connection is down");
}
}
return ConditionEvaluationResult.enabled("No assumptions, moving on...");
}
}
Hence, we can do the following in our tests.
@Test
@SkipWhenEndpointUnavailable(uri = "https://www.google.com")
void call2() {
Assertions.assertTrue(HttpCaller.call("https://www.google.com"));
}
We can go ahead and add @Test
annotation over @SkipWhenEndpointUnavailable
and remove it from our test code. Like, so:
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(EndpointAvailabilityCondition.class)
@Test
public @interface SkipWhenEndpointUnavailable {
String uri();
}
class HttpCallerTest {
@SkipWhenEndpointUnavailable(uri = "https://www.google.com")
void call2() {
Assertions.assertTrue(HttpCaller.call("https://www.google.com"));
}
}
I hope it helps.
Upvotes: 20