doAnswer() equivalent in Spock - junit

I am new to Spock and trying to achieve below scenario:
#Test
public void asynchronousMethodTest() {
JsonObject jsonObject = new JsonObject();
jsonObject.put("name", "Lilly").put("city", "Glendale");
AsyncResult<JsonObject> asyncResult = Mockito.mock(AsyncResult.class);
when(asyncResult.succeeded()).thenReturn(true);
when(asyncResult.result()).thenReturn(jsonObject);
doAnswer(new Answer<AsyncResult<JsonObject>>() {
#Override
public AsyncResult<JsonObject> answer(InvocationOnMock invocation) throws Throwable {
((Handler<AsyncResult<JsonObject>>) invocation.getArguments()[1]).handle(asyncResult);
return null;
}
}).when(someService).callSomeService(Mockito.any(), Mockito.any());
childVerticle.asynchronousMethod();
//verify(someService, times(1)).callSomeService(Mockito.any(), Mockito.any());
}
What is spock equivalent to the above code?

Yes it's possible, please have a look at this part of the documentation. Here's the relevant part:
subscriber.receive(_) >> { args -> args[0].size() > 3 ? "ok" : "fail" }
where subscriber is defined a a Mock.

Related

Unit test for Spring KafkaListener with "Acknowledge" interface as an argument

I'm not expert at unit test but trying to write unit test for :
#KafkaListener(id = "group_id", topics = "topic" )
public AvroObject listen(AvroObject test, Acknowledgment ack)
But no idea how I can make it when there is and interface as an argument. I try this but not sure is it something useful or not make sense as an test :
#InjectMocks
KafkaConsumer kafkaConsumerTest;
#Test
#DisplayName("Assert Valid Consume")
void consumeValidEvent() throws URISyntaxException, IOException, InterruptedException {
// given
AvroObject event = createEvent(); //Create sample object as AvroObject
// when
AvroObject response = kafkaConsumerTest.listen(event, new Acknowledgment() {
#Override
public void acknowledge() {
}
#Override
public void nack(long sleep) {
//do nothing
}
// then
assertNotNull(response);
assertEquals(response.getCode1() ,98765);
assertEquals(response.getCode2() ,123456);
}
I was wondering if you can give me the best approach for this situation! cheers

mockito simulate test exception thrown by service

I am trying to test exception thrown from service when I use the instance of it.
Like I am trying to use Imock in Trans.class and use IMock method.
Below is the code
public class MockImpl implements IMock{
public String external(String str) throws Exception {
if(str.equals("throw")){
throw new Exception("Thrown exception.");
}
return str;
}
}
public class Trans {
private IMock mc;
public static int failed;
public String performTrans(String str) throws Exception {
return call(str);
}
private String call(String str) throws Exception {
mc = new MockImpl();
try {
return mc.external(str);
}
catch(Exception e){
failed++;
throw e;
}
}
}
In test class I am trying to do this
public class TestMock {
#Test
public void testMock() throws Exception {
Trans trans = mock(Trans.class);
IMock iMock = mock(IMock.class);
doThrow(new Exception()).when(iMock).external(any(String.class));
for(int i =0;i<10 ;i++){
trans.performTrans("any");
}
System.out.println(Trans.failed);
assertEquals(9, Trans.failed);
}
}
As I am new to this, I am not sure if my understanding is correct, what I am trying to achieve is
When I do # Trans.performTrans(String);
Then doThrow(new Exception()).when(iMock).external(any(String.class)); should happen. How can I tell Mockito or any test framework that The exception should be thrown should be simulated from the Imock service method, even if it is indirectly called.
UPDATE
After trying to test this way
#RunWith(MockitoJUnitRunner.class)
public class TestMock {
#Test
public void testMock() throws Exception {
Trans trans = new Trans();
IMock iMock = mock(IMock.class);
trans.setInter(iMock);
//doThrow(new Exception()).when(iMock).external(any(String.class));
trans.performTrans("abc");
verify(iMock).external(new String("a"));
System.out.println(Trans.failed);
assertEquals(9, Trans.failed);
}
}
I get this error.
Wanted but not invoked: iMock.external("a");
-> at com.app.TestMock.testMock(TestMock.java:32) Actually, there were zero interactions with this mock.
what could be wrong?

Assert null is not working as actual method changes the value

I am trying to write a Junit for a piece of code for asserting the value as null. But the value is changing on the actual call.
Main Class Code
#Activate
public void activate(ComponentContext context)
{
myNotificationSubscriber = NotificationSubscriber.newInstance(myGlobalTableNotificationService,
NotificationType.ENTITIES,
this);
setWantedSubscriptionStatus();
LOG.debug("Activating {} service", getClass().getName());
try
{
applyConfigUpdate(context, IS_ACTIVATION);
}
catch (ServiceNotAvailableException e)
{
String instanceNameWithException = COUNTER_INSTANCE_COBA.concat("-")
.concat(String.valueOf(e.getResponseCode().getResponseCode()))
.concat(e.getClass().getSimpleName());
myCounterregistrator.get()
.incrementCounter(Counter.DATAACCESS_COBA_RESPONSE_UNSUCCESSFUL.getCounterInstance(instanceNameWithException));
LOG.debug("Can not activate Component :{}", e.getMessage());
}
LOG.info("COBA Cache state is {}", myCacheState);
}
private GlobalTableRetriever getGlobalTableRetrieverer() throws ServiceNotAvailableException
{
GlobalTableRetriever tableFetcher = myGlobalTableRetriever.get();
if (tableFetcher == null)
{
throw new ServiceNotAvailableException(RETRIEVER_SERVICE_NOT_AVAILABLE_MSG, ResponseCode.COBA_READ_DATA_TEMPORARY_ERROR);
}
return tableFetcher;
}
I want to write the test for the catch block. So tried to write the test case in below.
#Test
public void testapplyConfigUpdate() throws GlobalTableException
{
exception.expect(ServiceNotAvailableException.class);
globalTableRetriever.set(null);
tableFetcher = globalTableRetriever.get();
assertThat(tableFetcher).isNull();
myTableHandler.activate(myOsgiComponentContext);
verify(myCounterRegistratorService, times(1)).incrementCounter(any(CounterInstance.class));
}
But once its entering to getGlobalTableRetrieverer method, the assertion null value is changing to original.
Why do you even need to assert that?
exception.expect(ServiceNotAvailableException.class);
already implies that tableFetcher is null.
Just try this :
#Test
public void testapplyConfigUpdate() throws GlobalTableException
{
exception.expect(ServiceNotAvailableException.class);
globalTableRetriever.set(null);
tableFetcher = globalTableRetriever.get();
}

Test with JUnit an request

I wanna to test an request with JUnit with an request like this but RxUtils.applySchedulersAndErrorMapper() return null. Is any possibilities to test that?
override fun onContinueClicked(phoneNumber: String) {
mView.showLoading()
mUserService.checkUserApprovedStatus(phoneNumber)
.compose(RxUtils.applySchedulersAndErrorMapper())
.subscribe({ response ->
//Success
}, { error ->
//Error
})
}
here is where I setup the presenter and mUserService for presenter
#Mock
private PhoneContract.View view;
#Mock
private UserService userService;
#Before
public void setup() {
presenter = new PhonePresenter(this.view);
presenter.mUserService = userService;
}
here is the test method
#Test
public void onContinueClicked_SendJustNumbers() {
String phoneNumber = "(01234567890)";
// when
presenter.onContinueClicked(phoneNumber);
// then
verify(view, times(1)).showLoading();
}
and here is the RXUtils class:
class RxUtils {
companion object {
#SuppressLint("CheckResult")
fun <E> applySchedulersAndErrorMapper(): ObservableTransformer<E, E> {
return ObservableTransformer { o ->
o.flatMap(Function<E, ObservableSource<E>> { element ->
val genericResponse = element as GenericResponse<*>
#Suppress("UNCHECKED_CAST")
return#Function Observable.just(genericResponse as E)
}).onErrorResumeNext(Function<Throwable, ObservableSource<E>> { t ->
if (t is ApiException) {
return#Function Observable.error(t)
}
var genericResponse: GenericResponse<*>? = null
return#Function Observable.error(ApiException(t.message ?: "", genericResponse?.result ?: Result()))
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
}
}
}
}
Here is the stacktrace where I receive null for RxUtils.applySchedulersAndErrorMapper()
java.lang.NullPointerException
If it relates to the SDK, it probably won't work in a unit test. You didn't include your imports, so it's impossible to tell at a glance, but I know from experience that you can't use this in a unit test
AndroidSchedulers.mainThread()
You need to replace that with, say, Schedulers.trampoline()
Example of how to set a custom scheduler for testing
Note, this is only an example, and there are other valid solutions.
class RxUtils {
companion object {
// add this
#VisibleForTesting var mainScheduler = AndroidSchedulers.mainThread()
#VisibleForTesting var ioScheduler = Schedulers.io()
#SuppressLint("CheckResult")
fun <E> applySchedulersAndErrorMapper(): ObservableTransformer<E, E> {
return ObservableTransformer { o ->
o.flatMap(Function<E, ObservableSource<E>> { element ->
val genericResponse = element as GenericResponse<*>
#Suppress("UNCHECKED_CAST")
return#Function Observable.just(genericResponse as E)
}).onErrorResumeNext(Function<Throwable, ObservableSource<E>> { t ->
if (t is ApiException) {
return#Function Observable.error(t)
}
var genericResponse: GenericResponse<*>? = null
return#Function Observable.error(ApiException(t.message ?: "", genericResponse?.result ?: Result()))
})
.observeOn(mainScheduler)
.subscribeOn(ioScheduler)
}
}
}
}
And in your test:
#Before fun setup() {
RxUtils.mainScheduler = Schedulers.trampoline()
RxUtils.ioScheduler = Schedulers.trampoline()
}
#After fun teardown() {
RxUtils.mainScheduler = AndroidSchedulers.mainThread()
RxUtils.ioScheduler = Schedulers.io()
}
EDIT in response to updated post with more information on test
First of all, you should post WAY MORE CODE. It's frustrating having to pull it out of you by dribs and drabs. Anyway. You have the following:
#Mock
private UserService userService;
That creates a mock UserService, sure, but it doesn't stub anything. When you call userService.anyFunctionAtAll(), it will return null by default. There's your NPE. You have to stub it. For example:
Mockito.when(userService.anyFunctionAtAll()).thenReturn(somePredeterminedValue)
Please refer to the Mockito website for more information.

rxjava - How to handle merge exceptions without terminating the whole process

I have created two observables.
One of them throws an exception.
obs1 = Observable.from(new Integer[]{1, 2, 3, 4, 5, 6});
obs2 = Observable.create(new Observable.OnSubscribe<Integer>() {
#Override public void call(Subscriber<? super Integer> subscriber) {
boolean b = getObj().equals(""); // this throws an exception
System.out.println("1");
}
});
Now I invoke them using
Observable.merge(obs2, obs1)
.subscribe(new Observer<Integer>() {
#Override public void onCompleted() {
System.out.println("onCompleted");
}
#Override public void onError(Throwable throwable) {
System.out.println("onError");
}
#Override public void onNext(Integer integer) {
System.out.println("onNext - " + integer);
}
});
Now, I dont want my process to halt completely when an exception occurs -
I want to handle it and I want obs1 to continue its work.
I have tried to write it using onErrorResumeNext(), onExceptionResumeNext(), doOnError()
but nothing helped - obs1 did not run.
How can I handle the exception without stopping the other observable from being processed?
Sounds like you need mergeDelayError.
The problem is in your subscriber which is broken. You should catch your exception and call onError. Otherwise, you broke the rx contract.
example :
Observable<Integer> obs1 = Observable.from(Arrays.asList(1, 2, 3, 4, 5, 6));
Observable<Integer> obs2 = Observable.create((Subscriber<? super Integer> subscriber) -> {
subscriber.onError(new NullPointerException());
});
Observable.merge(obs2.onErrorResumeNext((e) -> Observable.empty()), obs1)
.subscribe(new Observer<Integer>() {
#Override public void onCompleted() {
System.out.println("onCompleted");
}
#Override public void onError(Throwable throwable) {
System.out.println("onError");
}
#Override public void onNext(Integer integer) {
System.out.println("onNext - " + integer);
}
});
so if you replace your obs2 code with this, it should work like you expected :
obs2 = Observable.create(new Observable.OnSubscribe<Integer>() {
#Override public void call(Subscriber<? super Integer> subscriber) {
try {
boolean b = getObj().equals(""); // this throws an exception
System.out.println("1");
} catch(Exception ex) {
subscriber.onError(ex);
}
}
});