How would one unit test api call method (rxjava+retrofit)? - unit-testing

I'm trying to unit test an api call made with retrofit and rxjava.
In order to do that i'm mocking the api call object but api calls subscriber won't trigger its onNext method.
ApiCallsTest.java:
//custom object replacing api call response object
Observable<FastRechargeClass[]> apiObservable = Observable.just(fastRechargeList);
InterfaceAPI api = mock(InterfaceAPI.class);
when(retrofitApi.getApiInterface(context)).thenReturn(api); when(api.getLatestTransactions("token")).thenReturn(apiObservable);
apiCalls.getLatestTransactions("token",context);
ApiCalls.java:
public void getLatestTransactions(String token, final Context context) {
String methodName = "getLatestTransactions";
InterfaceAPI api = retrofitApi.getApiInterface(context);
Observable<FastRechargeClass[]> call = api.getLatestTransactions(token);
call.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(new Observer<FastRechargeClass[]>() {
#Override
public void onSubscribe(Disposable d) {
WriteLog.print("onSubscribe");
}
#Override
public void onNext(FastRechargeClass[] fastRechargeClasses) {
fastRechargeManager.runUpdateFastRechargeDb(fastRechargeClasses);
}
#Override
public void onError(Throwable e) {
logOnFailureRequests(methodName, e.getMessage());
}
#Override
public void onComplete() {
}
});
}
When running test
onSubscribe is being called and it stops

You need to trigger event emission manually. To do this you need to call method
.blockingFirst()
or
.blockingGet()
depends of observable type you are using.
So you have to add
call.blockingGet()
at the end of getLatestTransactions method or this method should return created observable and call blocking get inside a test method.

Related

Fake internal calls of a SUT with FakeItEasy

I have a small C# class that handles printing.
I want to create (n)unit tests for this class, using
fakeItEasy. How can I fake the internal calls of this
class without faking the whole SUT ?
For example:
public class MyPrintHandler: IMyPrintHandler
{
public MyPrintHandler(ILogger<MyPrintHandler> logger)
{
}
// function I want to (unit test
public async Task<bool> PrintAsync(string ipaddress)
{
try
{
if (!string.IsNullOrWhiteSpace(ipaddress) )
{
return await StartPrint(ipaddress); // This cannot be called in a unit test, because it really start printing on a printer.
}
}
catch (Exception e)
{
}
return false;
}
private async Task<bool> StartPrint(string ipaddress)
{
// prints on the printer
}
[TestFixture]
public class MyPrintHandlerTests
{
[Test]
public void Succes_PrintAsync()
{
using (var fake = new AutoFake())
{
// Arrange - configure the fake
var sut = fake.Resolve<MyPrintHandler>();
// Act
await sut.PrintAsync("0.0.0.0"); // I want to prevent StartPrint() from being called..
}
}
}
How can I achieve this, or is this not possible at all?
Thanks in advance!
I would typically say that faking the SUT is an anti-pattern, to be avoided whenever possible, as it causes confusion. If you can refactor to introduce a collaborator that handles the StartPrinting method, I would strongly consider doing so. If this is not possible, you can try this, however
any method that you want to fake must be virtual or abstract, otherwise FakeItEasy cannot intercept it
any method that you want to fake must be public (or internal, if you can grant dynamic proxy access to production code's internals)
you would then fake the SUT, specifying that it should call the original (base) methods, and finally
explicitly override the behaviour for the method that you want to intercept

How to test if my application method handles HTTP status 404 of a REST API without actually calling that REST API

I am currently trying to automate some of the testing for my application using JUnit. My application has a method which calls a 3rd party REST API. I need to check if that method is handling HTTP status codes like 404 without actually calling the 4rd party API.
e.g., My Method:
public int getNumUsers(){
//call the 3rd party API - https://example.com/api/users/count
//return user count
}
I need to test if the method getNumUsers is handling HTTP status code 404 which could be returned by the 3rd party API - https://example.com/api/users/count.
Any suggestions?
Extract the the http call to the "3rd party API" into its own object. Pass that object into the constructor of the class you want to test.
Now you can replace this in your unit test with a test double (stub/mock) and control what it returns. A proper result value or an error.
Something like this:
this is the 3rd part API
interface UserApi {
int getUserCount ();
}
your user service will call this api
class UserService {
private final UserApi api;
UserService(UserApi api) {
this.api = api;
}
int getUserCount() {
// todo handle errors
return api.getUserCount ();
}
}
and some tests
public class UserServiceTest {
#Test
public void shouldProvideUserCount() {
UserService service = new UserService (new UserApi () {
#Override
public int getUserCount () {
return 1;
}
});
// when
int count = service.getUserCount ();
// then
assertEquals(1, count);
}
#Test(expected = UserOperationFailedException.class)
public void shouldHandleApiError() {
UserService service = new UserService (new UserApi () {
#Override
public int getUserCount () {
throw new ApiException();
}
});
// when
service.getUserCount ();
}
}
You can use a library like Mockito to create the stub instead of implementing it yourself.

AWS Lambda - Asynchronously invoked function but nothing happens

I have 2 lambda functions, my first function w/c we'll call "PostStep" invokes another lambda function "RetryStep" asynchronously whenever a timeout occurs. It's been working fine ever since. Now I have to do some code changes, and during testing, a weird issue occurred.
Upon timeout, it still calls the RetryStep function asynchronously, but then the function is not really being invoked. I tried invoking the PostStep function again, then I noticed that's the time when the RetryStep function is really invoked, but with the previous request's data.
Here's how I'm doing the invocation:
LivePostingService.class
#Override
public void postTransaction(Transaction transaction) {
... some posting logic ...
conditionalCallRetryLambdaFunction(transaction);
}
private void conditionalCallRetryLambdaFunction(Transaction transaction) {
try {
String payload = objectMapper.writeValueAsString(transaction);
lambdaInvokerService.invokeAsync(lambdaRetryFunctionName, payload);
} catch (JsonProcessingException e) {
if(LOGGER.isErrorEnabled()) {
LOGGER.error(e.getMessage(), e);
}
}
}
LambdaInvokerService.class
#Service
public class LambdaInvokerServiceImpl implements LambdaInvokerService {
LOGGER.info("Calling lambda function: " + functionName + ", with payload: " + payload);
InvokeRequest req = new InvokeRequest()
.withFunctionName(functionName)
.withInvocationType(InvocationType.Event)
.withPayload(payload);
AsyncHandler<InvokeRequest, InvokeResult> asyncHandler = new AsyncHandler<InvokeRequest, InvokeResult>() {
#Override
public void onError(Exception e) {
LOGGER.error(e.getMessage());
}
#Override
public void onSuccess(InvokeRequest request, InvokeResult invokeResult) {
LOGGER.info("Success! " + invokeResult);
}
};
lambdaAsyncClient.invokeAsync(req, asyncHandler);
}
Here's my handler:
#Override
public Void handleRequest(DynamodbEvent dynamodbEvent, Context context) {
livePostingService.postTransaction(transaction);
return null;
}
As you can see from the code, the log Calling lambda function.. appears at the end of PostStep function, but the log Success! appears at the beginning of the PostStep function if i invoke it again.
It's the same code with what's currently on our production. I even did a git checkout on our master branch then ran it on dev, but the same issue still occurs. Do you have any idea about this?
Thanks!

How to mock a retrofit service observable calling onError?

I am testing this code.
service.getProducts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Result<Catalog<SoajsProductPreview>>>() {
#Override
public void onError(Throwable e) {
view.showErrorView(e);
}
#Override
public void onNext(Result<Product> products) {
view.showProducts(products)
}
#Override
public void onCompleted() {}
});
Testing that view.showProducts() the mocked service returns results works fine.
I do
when(service.getProducts().thenReturn(someObservable);
Now I want to test that view.ShowErrorView() is called when the service throws an error but I can't find a way to do that:
Obviously the following doesn't compile
when(service.getProducts().thenReturn(someException);
And this throws an exception immediately but doesn't call the Subscriber's onError method
when(service.getProducts().thenReturn(someException);
How can I get Subscriber.onError() called?
when(service.getProducts().thenReturn(Observable.error(someException))
should work. See the documentation starting here.

How to mock the parameter in an anonymous callback by using mockito?

I want to unit test my code below with Mockito, could anyone let me know how I can mock the response from the callback, which is anonymous in my code? Particularly, how can I verify if doSomethingOnResponse() gets called with the mocked response?
public void runTask() {
Data data = null;
ClassA objA = new ClassA(new Callback() {
#Override
public void onResponse(Response response) {
data = getSomethingFromResponse(response);
}
};
//this is a synchronous call
objA.run();
doSomethingElse(data); //data gets assigned from the callback
}
Thanks a lot in advance!