如何在 Presenters 方法中模拟新创建的对象?
How to mock newly created objects inside Presenters method?
我有使用 payWorkOrder() 方法的 PaymentPresenter。该方法接受一些参数并根据逻辑创建两个新对象:
- 我付
- 付款请求
这是代码:
@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);
}
}
}
这是我的单元测试:
@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);
}
这里抛出异常:
Disposable disposable = workOrdersRepository.payWorkOrderInvoice(workOrderId, new PaymentRequest(woPayment))
.subscribeOn(Schedulers.io())
但失败并显示以下堆栈跟踪:
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.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.access0(PowerMockJUnit47RunnerDelegateImpl.java:59)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$LastRuleTestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:148)
at
com.test.presentation.core.TrampolineSchedulerRule.evaluate(TrampolineSchedulerRule.java:21)
模拟时看起来有问题
您正在使用
Mockito.when(workOrdersRepository.payWorkOrderInvoice(workOrderId,
paymentRequest)).thenReturn(Single.just(response));
NPE 的原因是 paymentRequest 而 mocking 与以下代码中传递的不同
Disposable disposable = workOrdersRepository.payWorkOrderInvoice(workOrderId, new PaymentRequest(woPayment))
.subscribeOn(Schedulers.io())
在 return 中它什么也没给出,而原始代码正在订阅它并抛出空指针异常
尝试 any(PaymentRequest.class) 以及 workOrderId anyInteger()。
我有使用 payWorkOrder() 方法的 PaymentPresenter。该方法接受一些参数并根据逻辑创建两个新对象:
- 我付
- 付款请求
这是代码:
@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);
}
}
}
这是我的单元测试:
@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);
}
这里抛出异常:
Disposable disposable = workOrdersRepository.payWorkOrderInvoice(workOrderId, new PaymentRequest(woPayment))
.subscribeOn(Schedulers.io())
但失败并显示以下堆栈跟踪:
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.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.access0(PowerMockJUnit47RunnerDelegateImpl.java:59) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$LastRuleTestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:148) at com.test.presentation.core.TrampolineSchedulerRule.evaluate(TrampolineSchedulerRule.java:21)
模拟时看起来有问题
您正在使用
Mockito.when(workOrdersRepository.payWorkOrderInvoice(workOrderId, paymentRequest)).thenReturn(Single.just(response));
NPE 的原因是 paymentRequest 而 mocking 与以下代码中传递的不同
Disposable disposable = workOrdersRepository.payWorkOrderInvoice(workOrderId, new PaymentRequest(woPayment))
.subscribeOn(Schedulers.io())
在 return 中它什么也没给出,而原始代码正在订阅它并抛出空指针异常
尝试 any(PaymentRequest.class) 以及 workOrderId anyInteger()。