Zookey
Zookey

Reputation: 2707

How to mock newly created objects inside Presenters method?

I have PaymentPresenter with method payWorkOrder(). That method accepts some parameters and based on the logic created two new objects:

  1. WoPayment
  2. PaymentRequest

Here is the code for that:

@RunWith(PowerMockRunner.class) @PrepareForTest({TextUtils.class, WoPayment.class, PaymentRequest.class})
public class PaymentPresenterTest extends BaseTest {

@Rule TrampolineSchedulerRule trampolineSchedulerRule = new  TrampolineSchedulerRule();

@Mock CustomersRepository customersRepository;
@Mock AgreementsRepository agreementsRepository;
@Mock WorkOrdersRepository workOrdersRepository;
@Mock PaymentPresenter.View view;
@Mock ResponseBody responseBody;

private PaymentPresenter presenter;

@Before public void setUp() {
mockTextUtils();
presenter = new PaymentPresenter(customersRepository,  agreementsRepository, workOrdersRepository);
presenter.setView(view);
}

public void payWorkOrderInvoice(int workOrderId, double amount, String paymentMethod, String checkNumber) {
disposables = RxUtil.initDisposables(disposables);

WoPayment woPayment = new WoPayment();

if(amount > 0) {
  woPayment.setAmount(amount);
} else {
  view.displayAmountShouldBeGreaterThanZero();
  return;
}

if(TextUtils.isEmpty(paymentMethod)) {
  view.displayPaymentMethodInvalid();
  return;
} else {
  woPayment.setPaymentMethod(paymentMethod);
}

if(paymentMethod.equalsIgnoreCase("Check") && TextUtils.isEmpty(checkNumber)) {
  view.displayReferenceNumberError();
  return;
} else {
  woPayment.setCheckNumber(checkNumber);
}

view.disablePayButton();

Disposable disposable = workOrdersRepository.payWorkOrderInvoice(workOrderId, new PaymentRequest(woPayment))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(response -> {
      if(response.isSuccessful()) {
        view.displayWorkOrderInvoicePaid(response.body());
      } else {
        view.enablePayButton();
        view.displayWorkOrderInvoiceNotPaid();
      }
      }, throwable -> {
      view.enablePayButton();
      view.handleError(throwable);
    });

disposables.add(disposable);
}
}
}

Here is my unit test:

@Test public void shouldPayWorkOrderInvoice() {
// Given
int workOrderId = 1;
double amount = 1.0;
String paymentMethod = "cash";
String checkNumber = "1";
WorkOrderDetails workOrderDetails = Mockito.mock(WorkOrderDetails.class);
Response<WorkOrderDetails> response = Response.success(200, workOrderDetails);
WoPayment woPayment = new WoPayment();
woPayment.setAmount(amount);
woPayment.setCheckNumber(checkNumber);
woPayment.setPaymentMethod(paymentMethod);
PaymentRequest paymentRequest = new PaymentRequest(woPayment);

// When
Mockito.when(workOrdersRepository.payWorkOrderInvoice(workOrderId, paymentRequest)).thenReturn(Single.just(response));
presenter.payWorkOrderInvoice(workOrderId, amount, paymentMethod, checkNumber);

// Then
Mockito.verify(view).displayWorkOrderInvoicePaid(workOrderDetails);
}

It throws exception here:

Disposable disposable = workOrdersRepository.payWorkOrderInvoice(workOrderId, new PaymentRequest(woPayment))
.subscribeOn(Schedulers.io())

But it fails with the following stacktrace:

java.lang.NullPointerException at com.test.presentation.agreements.payment.PaymentPresenter.payWorkOrderInvoice(PaymentPresenter.java:168) at com.test.presentation.agreements.PaymentPresenterTest.shouldPayWorkOrderInvoice(PaymentPresenterTest.java:175) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310) at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89) at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$LastRuleTestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:148) at com.test.presentation.core.TrampolineSchedulerRule$1.evaluate(TrampolineSchedulerRule.java:21)

Upvotes: 0

Views: 45

Answers (1)

Swarit Agarwal
Swarit Agarwal

Reputation: 2648

Looks issue in mocking

you are using

Mockito.when(workOrdersRepository.payWorkOrderInvoice(workOrderId, paymentRequest)).thenReturn(Single.just(response));

Reason of NPE is paymentRequest while mocking is not same as passed in following code

Disposable disposable = workOrdersRepository.payWorkOrderInvoice(workOrderId, new PaymentRequest(woPayment))
.subscribeOn(Schedulers.io())

In return it gave nothing while original code is subscribing on it and throwing null pointer exception

Try any(PaymentRequest.class) as well as instead workOrderId anyInteger().

Upvotes: 1

Related Questions