模拟接口与类

时间:2019-01-31 17:10:02

标签: java mockito

我的接口定义如下:

public interface HttpClient {
    public <T> UdemyResponse<T> get(Request request,
      JSONUnmarshaler<T> unmarshaller, Gson gson)
      throws UdemyException, IOException;
}

我有一个类实现接口:

public class OkHttp implements HttpClient {
public OkHttpClient client;

final Logger logger = LoggerFactory.getLogger(getClass());

public OkHttp() {
    this.client = new OkHttpClient();
}

@Override
public <T> UdemyResponse<T> get(Request request, JSONUnmarshaler<T> unmarshaller, Gson gson)
        throws UdemyException, IOException {

int status_code = 0;
        String next = null;
        String rawJSON = null;
        JsonElement jsonelement = null;

    Boolean retry = true;
    int attempts = 3;

    while ((attempts >= 0) && (retry) && status_code != 200) {
        try {
            Response response = this.client.newCall(request).execute();

            rawJSON = response.body().string();

            jsonelement = gson.fromJson(rawJSON, JsonElement.class);

            next = gson.fromJson(jsonelement.getAsJsonObject().get("next"), String.class);

            status_code = response.code();

            if (status_code == 401) {
                try {
                    logger.warn("token expired");
                    TimeUnit.SECONDS.sleep(5);
                    retry = true;
                    continue;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if ((status_code / 100) == 5) {
                logger.warn("gateway error");
                retry = true;
                continue;
            }

        } catch (IOException e) {
            e.printStackTrace();
            // this exception will be propagated to the main method and handled there to exit the program,
            // this exception should end the program.
            throw e;

        }

        attempts -= 1;
        retry = false;

    }   
    if (status_code != 200) {
        throw new UdemyException();
    }

    return new UdemyResponse<T>(status_code, next, rawJSON,
            unmarshaller.fromJSON(gson, jsonelement.getAsJsonObject()));

}

如果我模拟接口,我可以为get()方法编写测试用例,但我的get()方法使用this.client,我也需要模拟该对象。

在这种情况下,模拟OkHttp对象而不是接口更好吗?

2 个答案:

答案 0 :(得分:0)

如果您尝试测试get(),那么您不应该模拟该方法,如果这样做,您正在测试的是什么?您需要模拟get()的其他依赖关系,以帮助您进行隔离测试。在这种情况下,如果this.client是get()的依赖项,那么这就是您需要模拟的内容。

答案 1 :(得分:0)

根据问题的变化进行了编辑

这很糟糕:(status_code / 100)。 在此测试真实状态代码。

您应该执行以下操作:

  1. 创建一个模拟OkHttpClient
  2. 使用反射将模拟程序注入测试类。
  3. 测试的get方法。

您可能想在下面的代码中更改对正常情况的模仿, 但你应该能够只使用简单的嘲弄的Mockito的一切。 这是一些示例代码:

public class TestOkHttp
{
  private static final String VALUE_JSON_STRING "some JSON string for your test";

  private OkHttp classToTest;

  @Mock
  private ClassWithExecute mockClassWithExecute;

  @Mock
  private OkHttpClient mockOkHttpClient;

  @Mock
  private Response mockResponse;

  @Mock
  private ResponseBodyClass mockResponseBodyClass;

  @Mock
  private Request mockRequest;

  private Gson testGson;

  @Test
  public void get_describeTheTest_expectedResults()
  {
    final JSONUnmarshaler<someclass> unmarshallerForThisTest = new JSONUnmarshaler<>()

    // setup the mocking functionality for this test.
    doReturn(desiredStatusCode).when(mockResponse).code();


    classToTest.get()
  }

  @Before
  public void preTestSetup()
  {
    MockitoAnnotations.initMocks(this);

    classToTest = new OkHttp();

    testGson = new Gson();

    doReturn(mockResponse).when(mockClassWithExecute).execute();

    doReturn(mockClassWithExecute).when(mockOkHttpClient).newCall(mockRequest);

    doReturn(mockResponseBodyClass).when(mockResponse).body();

    doReturn(VALUE_JSON_STRING).when(mockResponseBodyClass).string();

    ReflectionTestUtils.setField(classToTest,
      "client",
      mockOkHttpClient);
  }
}