我想在我的类中测试onFailure
方法,并检测post
实例上是否调用了BUS
方法。
我一直在努力,但我无法完成。我使用powermock和Mockito和junit。
ApiCallback.java:
package com.example.android.webserver;
import com.example.android.event.OnApiRequestErrorEvent;
import com.example.android.event.OnApiResponseErrorEvent;
import com.example.android.model.ApiRequestError;
import com.example.android.utils.BusProvider;
import com.example.android.utils.ErrorUtils;
import org.greenrobot.eventbus.EventBus;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public abstract class ApiCallback<T> implements Callback<T> {
private final static EventBus BUS;
static {
BUS = BusProvider.getInstance();
}
@Override
public void onFailure(Call<T> call, Throwable t) {
BusProvider.getInstance().post(new OnApiRequestErrorEvent(new ApiRequestError(t.getMessage())));
}
protected void handleResponse(Response<?> response, Object object) {
if (response.isSuccessful()) {
BusProvider.getInstance().post(object);
} else {
BUS.post(new OnApiResponseErrorEvent(ErrorUtils.parseError(response), object));
}
}
}
我的测试类 - ApiCallbackTest.java:
package com.ashojash.android.webserver;
import com.ashojash.android.utils.BusProvider;
import org.greenrobot.eventbus.EventBus;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.*;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import retrofit2.Call;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.doCallRealMethod;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
@RunWith(PowerMockRunner.class)
@PrepareForTest({BusProvider.class})
public class ApiCallbackTest {
@Mock
private ApiCallback apiCallback;
@Mock
private Call call;
@Mock
private Throwable throwable;
@Before
public void setUp() {
}
@Test
public void should_call_busProvider_to_post_event() throws Exception {
// given
doCallRealMethod().when(apiCallback).onFailure(any(Call.class), any(Throwable.class));
doCallRealMethod().when(BusProvider.getInstance());
// when
apiCallback.onFailure(call, throwable);
// then
EventBus bus = BusProvider.getInstace();
verify(bus).post(anyObject());
}
}
答案 0 :(得分:2)
一般来说,我对任何&#34;如何使用powermock&#34;的回答问题是:根本不使用它。
我花了太多时间在电源摇摆测试中突然失败......从来没有发现我的生产代码有任何问题。
恰恰相反:&#34;对电动摇摆的需求&#34;实际上是一个很好的指标,你想出了一个不可测试的设计。而不是使用powermock到&#34;锤&#34;将您的代码转换为似乎可测试的内容...您最好花时间修复您糟糕的设计。
请记住:PowerMock操纵你的字节代码,你不测试你的类,而是PowerMock从你的类创建的东西。
作为初学者,您可能希望至少观看此google tech series.
中的两个第一个视频答案 1 :(得分:2)
这是一个更好的重构案例。这样,您可以在包相邻测试中使用测试双精度,并且如果需要,可以在新的相邻类中覆盖。
public abstract class ApiCallback<T> implements Callback<T> {
private final EventBus bus;
public ApiCallback() {
this(BusProvider.getInstance());
}
/** Package-private for testing. */
ApiCallback(EventBus bus) {
this.bus = bus;
}
@Override
public void onFailure(Call<T> call, Throwable t) {
bus.post(new OnApiRequestErrorEvent(new ApiRequestError(t.getMessage())));
}
protected void handleResponse(Response<?> response, Object object) {
if (response.isSuccessful()) {
bus.post(object);
} else {
bus.post(new OnApiResponseErrorEvent(
ErrorUtils.parseError(response), object));
}
}
}
有关替代策略的更完整列表,请参阅How to use Mockito when we cannot pass a mock object to an instance of a class。
旁注:您正在测试的课程是抽象的。您可能需要考虑在测试中创建一个具体的子类(具有简单的实现)。我看到你使用Mockito来提供抽象方法,这是可能的,但它不能提供关于 API表面是否发生变化的有用数据点 - 这是值得测试的,作为外部代码(子类)将依赖该一般合同。
答案 2 :(得分:2)
您只能验证模拟对象上的方法调用。您必须模拟对BusProvider.getInstance()的调用结果,然后您将能够验证该模拟对象上的方法调用。
@RunWith(PowerMockRunner.class)
@PrepareForTest({BusProvider.class})
public class ApiCallbackTest {
@Mock
private ApiCallback apiCallback;
@Mock
private Call call;
@Mock
private Throwable throwable;
@Test
public void should_call_busProvider_to_post_event() throws Exception {
doCallRealMethod().when(apiCallback).onFailure(any(Call.class), any(Throwable.class));
PowerMockito.mockStatic(BusProvider.class);
EventBus eventBusMock = mock(EventBus.class);
when(BusProvider.getInstance()).thenReturn(eventBusMock);
apiCallback.onFailure(call, throwable);
EventBus bus = BusProvider.getInstace();
verify(bus).post(anyObject());
}
}