Webclient Junit test for specific status code - junit

I have a webclient which takes a specific action for specific status code ..
How can i write a junit to cover that specific piece to increase code coverage ?
return this.webClient.get()
.uri(requestURL)
.headers(httpHeaders -> httpHeaders.setBearerAuth(xxxAuthServiceImpl.getAccessToken()))
.accept(MediaType.APPLICATION_JSON).retrieve()
.onStatus(HttpStatus::is4xxClientError, response -> {
if (response.statusCode() == NOT_FOUND) {
LOGGER.error("data not found for the passed id");
return Mono.error(new EntityNotFoundException("data not found for the passed id"));
}
return Mono.error(new xxxAPIClientException());
}).bodyToMono(Object.class)
.onErrorMap(Predicate.not(EntityNotFoundException.class::isInstance), exception -> {
LOGGER.error("Error occurred while calling xxx search data by id api.", exception);
return new xxxAPIClientException(exception.getMessage());
}).block();
My existing Junit Test Cases look like this:-
#Test
void testDataSearchById_Success() throws Exception {
// set up
when(responseSpec.onStatus(any(), any())).thenReturn(responseSpec);
when(responseSpec.bodyToMono(Object.class)).thenReturn(Mono.just(buildDataSearchResponse()[0]));
// execute
final Object dataSearchResponseById = xxxSearchClientImpl.dataSearchById(SAMPLE_TEST_API_URL);
// assert
assertNotNull(dataSearchResponseById);
}
/**
* Tests data search by id method which calls xxx api and no data found error
* occurs.
* The method should throw EntityNotFoundException
*/
#Test
void testDataSearchById_Failure_EntityNotFoundException() {
// execute and assert
when(responseSpec.onStatus(any(), any())).thenReturn(responseSpec);
doThrow(EntityNotFoundException.class).when(responseSpec).bodyToMono(Object.class);
assertThrows(EntityNotFoundException.class, () -> xxxSearchClientImpl.dataSearchById(SAMPLE_TEST_API_URL));
}
/**
* Tests data search by id method which calls xxx api and an exception occurs.
* The method should throw xxxAPIClientException
*/
#Test
void testDataSearchById_Failure_xxxAPIClientException() {
// execute and assert
when(responseSpec.onStatus(any(), any())).thenReturn(responseSpec);
doThrow(xxxAPIClientException.class).when(responseSpec).bodyToMono(Object.class);
assertThrows(xxxAPIClientException.class, () -> xxxSearchClientImpl.dataSearchById(SAMPLE_TEST_API_URL));
}

Related

Spring WebFlux; unit testing exception thrown in Mono.map()

I have some code that returns Mono<List<UserObject>>. The first thing I want to do is check the List is not empty, and if it is, throw a NoUsersFoundException. My code looks like this:
IUserDao.java
Mono<List<UserAccount>> getUserProfiles(final Set<UserQueryFilter> filters,
final Set<String> attributes);
GetUserAccount.java
public Mono<UserAccount> doGetUserAccount() {
return userDao.getUserProfiles(filters, attributes)
.map(list -> {
if (CollectionUtils.isEmpty(list)) {
throw new NoUsersFoundException();
}
return list;
})
.map(this::removePermissions)
.map(this::removeDuplicates);
}
I want to write a unit test that will test that the NoUsersFoundException is thrown when userDao.getUserProfiles(filters, attributes) returns an empty list. When I use Mockito#when with a .thenReturn(), the test will, as expected, return immediately once userDao.getUserProfiles(...) is called without continuing the flow into the .map() where the list is checked and exception thrown.
#Mock
private IUserDao userDao;
private UserPolicies userPolicies;
#BeforeEach
public void init() {
userPolicies = new UserPolicies(Set.of("XYZ", USER_AFF, "123"),
Set.of(TestUserConstants.ID, TestUserConstants.SUBSCRIPTION_LEVEL));
}
#Test
void shouldThrowExceptionIfNoUsersFound() {
final Set<UserFilter> filters = new UserFilterBuilder().withId(ID)
.withSubscription(PREMIUM)
.build();
when(userDao.getUserProfiles(filters, userPolicies.getUserAttributeIds()))
.thenReturn(Mono.just(Collections.emptyList()));
testClass = new GetUserAccount(userDao,
userPolicies,
filters,
userPolicies.getUserAttributeIds());
assertThatThrownBy(() -> testClass.doGetUserAccount()).isInstanceOf(NoUsersFoundException.class);
}
I have tried .thenAnswer() but it essentially does the same thing as the method called is not a void:
userDao.getUserProfiles(filters, userPolicies.getUserAttributeIds()))
.thenAnswer((Answer<Mono<List>>) invocationOnMock -> Mono.just(Collections.emptyList()));
I can't see how using reactor.test.StepVerifier would work for this case.
i dont really understand what you are asking for, but we commonly dont "throw" exceptions in reactor. We return a Mono#error downstream, and different operators will react accordingly as the error travels downstream.
public Mono<List<Foobar> fooBar(filters, attributes) {
return daoObject.getUserProfiles(filters, attributes)
.map(list -> {
if (CollectionUtils.isEmpty(list)) {
// Return a mono#error
return Mono.error( ... );
}
return list;
})
}
And then test using the step verifier. With either expectNext or expectError.
// Happy case
StepVerifier.create(
fooBar(filters, attributes))
.expectNext( ... )
.verify();
// Sad case
StepVerifier.create(
fooBar(filters, attributes))
.expectError( ... )
.verify();

Conditionally skip a Junit 5 test

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.
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.
Using Assumptions.assumeTrue()/assumeFalse() methods
Assumptions 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.
Using JUnit 5 extension mechanisms.
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.

Applitools openBase() failed with com.applitools.eyes.EyesException

I'm unable to figure out why is this code failing, I browsed through Applitools tutorials and I can't figure out what is happening here.
This is the exception being thrown:
com.applitools.eyes.EyesException: eyes.openBase() failed
at com.applitools.eyes.EyesBase.openBase(EyesBase.java:1037)
at com.applitools.eyes.selenium.SeleniumEyes.open(SeleniumEyes.java:246)
at com.applitools.eyes.selenium.Eyes.open(Eyes.java:77)
at com.applitools.eyes.selenium.Eyes.open(Eyes.java:1374)
at BaseTests.validateWindow(BaseTests.java:49)
at SearchTests.testSearchByFullTitle(SearchTests.java:11)
This is SearchTests:
import org.junit.Test;
public class SearchTests extends BaseTests {
#Test
public void testSearchByFullTitle(){
String title = "Agile Testing";
page.search(title);
validateWindow();
}
}
Validate window method:
public void validateWindow(){
eyes.open(driver, "Automation Bookstore", "neka metoda npr: "+
Thread.currentThread().getStackTrace()[2].getMethodName());
eyes.checkWindow();
eyes.close();
}
and the class throwing the exception:
protected void openBase() throws EyesException {
openLogger();
int retry = 0;
do {
try {
if (isDisabled) {
logger.verbose("Ignored");
return;
}
sessionEventHandlers.testStarted(getAUTSessionId());
validateApiKey();
logOpenBase();
validateSessionOpen();
initProviders();
this.isViewportSizeSet = false;
sessionEventHandlers.initStarted();
beforeOpen();
RectangleSize viewportSize = getViewportSizeForOpen();
viewportSizeHandler.set(viewportSize);
try {
if (viewportSize != null) {
ensureRunningSession();
}
} catch (Exception e) {
GeneralUtils.logExceptionStackTrace(logger, e);
retry++;
continue;
}
this.validationId = -1;
isOpen = true;
afterOpen();
return;
} catch (EyesException e) {
logger.log(e.getMessage());
logger.getLogHandler().close();
throw e;
}
} while (MAX_ITERATION > retry);
throw new EyesException("eyes.openBase() failed");
}
After some debugging, I found that I had a typo in my API key. After fixing that, works as expected.
In my case, the same issue was caused by using null as a value for the testName parameter.
I didn't understand it from the beginning, cause I relied on the javadoc for the open function:
/**
* Starts a test.
*
* #param driver The web driver that controls the browser hosting the application under test.
* #param appName The name of the application under test.
* #param testName The test name. (i.e., the visible part of the document's body) or {#code null} to use the current window's viewport.
* #return A wrapped WebDriver which enables SeleniumEyes trigger recording and frame handling.
*/
public WebDriver open(WebDriver driver, String appName, String testName) {
RectangleSize viewportSize = SeleniumEyes.getViewportSize(driver);
this.configuration.setAppName(appName);
this.configuration.setTestName(testName);
this.configuration.setViewportSize(viewportSize);
return open(driver);
}

Handling Runtime Exception in CompletableFuture in java8

Below is the sample code I'm using to understand exception handling in completablefuture in java8.
If we make use of exceptionally method as per doc,
exceptionally method catches even runtime exception as well and proceeds to last block in the pipeline.
if we don't use exceptionally method then, it justs prints running and exits.
Correct me if my understanding isn't correct.
Question is Lets say if i want to throw runtime exception and want application to stop. Basically if i throw Runtime exception , it shouldn't proceed to next block in pipeline. How should i do that. Any pointers are helpful.
public static void main(String[] args) {
final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
System.out.println("running");
int i = 0;
if(i == 0) {
throw new RuntimeException("ding");
}
return "test";
}).exceptionally(it -> {
System.out.println(it.getMessage());
return "empty";
}).thenApply(it -> {
System.out.println("last block" + it);
return "dummy";
});
}
Try this:
public static void main(String[] args) {
try {
final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
System.out.println("running");
int i = 0;
if (i == 0) {
throw new RuntimeException("ding");
}
return "test";
}).exceptionally(it -> {
if (it.getMessage().contains("ding")) {
throw (RuntimeException) it;
}
System.out.println(it.getMessage());
return "empty";
}).thenApply(it -> {
System.out.println("last block" + it);
return "dummy";
});
retrieveName.join();
} catch (Exception e) {
System.out.println("main() exception, cause=" + e.getCause());
}
}
This is the output:
running
main() exception, cause=java.lang.RuntimeException: ding
I made 3 small changes to your code:
Wrapped it all in a try-catch
Threw a RuntimeException in exceptionally() for the "ding" exception.
Added a call to retrieveName.join(). From the Javadoc for CompletableFuture.join():
public T join​()
Returns the result value when complete, or throws an (unchecked) exception if completed exceptionally.
Update based on OP feedback ------->
Lets say if i want to throw runtime exception and want application to
stop. Basically if i throw Runtime exception , it shouldn't proceed to
next block in pipeline. How should i do that.
You can achieve what you want with just 2 changes to your code:
[1] Completely remove the exceptionally() callback so the CompletableFuture (CF) terminates with an exception. In exceptionally() in the OP code the exception was being swallowed rather than rethrown, and returning a CF, so the thenApply() method was still performed.
[2] Add a call to retrieveName.join() at the end of main(). This is a blocking call, but since the thread had terminated with an exception that 's not really relevant for the sample code. The join() method will extract the thrown RunTimeException and re-throw it, wrapped in a CompletionException.
Here's your modified code:
public static void main(String[] args) {
final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
System.out.println("running");
int i = 0;
if(i == 0) {
throw new RuntimeException("ding");
}
return "test";
}).thenApply(it -> {
System.out.println("last block" + it);
return "dummy";
});
retrieveName.join();
}
Notes:
This is not how to do things in Production. The blocking call from join() was not a problem here, but could be for a long running CF. But you obviously can't extract the exception from the CF until it is complete, so it makes sense that the join() call blocks.
Always bear in mind that main() is not running in the same thread(s) as the CF.
An alternative approach (if viable) might be to handle all the necessary post-exception actions (logging, etc,) within exceptionally() and then terminate normally with a suitable return value (e.g. "Exception handled!") rather than propagating the exception.
You can check whether the CF is still running by calling the non-blocking isDone() method. You can also check whether the CF ended with an exception (isCompletedExceptionally()) or was cancelled(isCancelled​()).

error when running map reduce in CouchBase Lite

I am trying to use map-reduce on CouchBase Lite. I have documents and they are being channelised. All doucments what I want are coming to Couchbase Lite. But When I Try to run map-reduce on them I am getting the following error
com.couchbase.lite.CouchbaseLiteException: Error when calling map block of view 'calendar', Status: 593 (HTTP 500 Application callback block failed)
Below is my map reduce function
private View createView(Database database){
View calendarView = database.getView("calendar");
calendarView.setMap(new Mapper() {
#Override
public void map(Map<String, Object> document, Emitter emitter) {
emitter.emit((long) document.get("date"),(long) document.get("cost"));
}
},"2");
return calendarView;
}
and Below is the part of main where I am calling the view and querying over it
View calendarView = createView(database);
Query query = database.getView("calendar").createQuery();
query.setStartKey(1472467249448l);
query.setEndKey(1472553649449l);
QueryEnumerator result = null;
try {
result = query.run();
} catch (CouchbaseLiteException e) {
e.printStackTrace();
}
for (Iterator<QueryRow> it = result; it.hasNext(); ) {
QueryRow row = it.next();
Log.d(TAG, row.getValue().toString());
}
As borrrden said in a comment above, Application callback block failed means your map function threw an exception. Use a debugger to find out what it is.
A likely possibility is that one of the documents in your database does not have a date property. In that case your map function would be passing null to the first (key) parameter of emit, which is an invalid argument.