检测是否使用 mockito 调用私有静态最终字段的方法



我想在我的类中测试onFailure方法,并检测post方法是否在BUS实例上被调用。

我已经试了一整天了,但我还是没有完成。我在junit中使用powermock和Mockito。

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());
 }
}

一般来说,对于任何"如何使用powermock"的问题,我的回答是:根本不要使用它。

我花了太多时间在powermock测试上,突然失败了…从来没有发现我的产品代码有任何问题。

相反:"需要powermock"实际上是一个很好的指标,表明您提出了一个不可测试的设计。而不是使用powermock来"锤击"你的代码到一些似乎可测试的东西…你最好花时间修复你的糟糕设计。

请记住:PowerMock操作您的字节码,您是在而不是测试您的类,而是PowerMock从您的类中创建的东西。

作为初学者,您可能希望至少观看这个google技术系列的前两个视频。

这是一个更好的重构案例。这样,您就可以在与包相邻的测试中使用test double,并且可以在需要时在新的相邻类中重写。

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));
    }
  }
}

有关更完整的替代策略列表,请参见当无法将模拟对象传递给类的实例时如何使用Mockito。

旁注:测试中的类是抽象的。您可能需要考虑在测试中创建一个具体的子类(带有一个简单的实现)。我看到您使用Mockito来提供抽象方法,这是可能的,但它不会提供关于API表面是否更改的有用数据点-这是值得测试的,因为外部代码(子类)将依赖于一般契约。

您只能在模拟对象上验证方法调用。您必须模拟调用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());
   }
}

相关内容

  • 没有找到相关文章

最新更新