1

我使用 Spring Android Rest Template 来执行 HTTP 请求。我是这样测试的:

package com.mnubo.platform.android.sdk.internal.user.services.impl;

import com.mnubo.platform.android.sdk.models.users.User;

import org.junit.Before;
import org.junit.Test;
import org.springframework.test.web.client.MockRestServiceServer;

import static org.springframework.http.HttpMethod.GET;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;

@RunWith(RobolectricTestRunner.class)
@Config(emulateSdk = 18)
public class DummyTest {

    private MyApiImpl myApi;
    private MockRestServiceServer myapiMockServer;

    @Before
    public void setUp() throws Exception {
    myApi = new MyApiImpl("ACCESS_TOKEN");//break here

    myapiMockServer = MockRestServiceServer.createServer(myApi.getRestTemplate());
    }

    @Test
    public void testRestClient() throws Exception {


    final User expectedUser = new User();
    expectedUser.setUsername("test");
    expectedUser.setLastname("lastname");

    myapiMockServer.expect(requestTo("http://my-service.com/user/test"))
            .andExpect(method(GET))
            .andRespond(withSuccess(this.convertToJsonString(expectedUser), APPLICATION_JSON_UTF8));

    User user = myApi.userOperations().getUser("test");
    userMockServer.verify();
    }
}

所有这些都使用 RoboelectricTestRunner 正常工作。但是,昨天 Android Studio 更新并要求我将构建工具版本更新为 1.1.0。(com.android.tools.build:gradle:1.1.0)。

此版本现在包括对单元测试的支持。请参阅https://sites.google.com/a/android.com/tools/tech-docs/unit-testing-support

问题:我不能再创建MyApiImpl了,因为它创建了一个 RestTemplate。这个 RestTemplate 使用 org.springframework.http.client.HttpComponentsClientHttpRequestFactory 并且在这个类的构造函数中,使用了来自 org.apache.http 包的方法。

这些方法引发了异常:例如:Method getSocketFactory in org.apache.http.conn.scheme.PlainSocketFactory

好吧,我使用 PowerMock 成功地模拟了 getSocketFactory 但随后我不得不模拟只能从构造函数( sourceregister本地访问的 SchemeRegistry 方法。

所以我放弃了尝试模拟 RestTemplate 内部发生的所有恶作剧,并决定直接模拟 RestTemplate。

我需要帮助来正确地模拟它,以便MockRestServiceServer仍然可以在我的测试中使用,因为现在,myapiMockServer.verify()断言失败了。

更新 我仍然无法使用来测试我的 Api,但我设法使用类似的模拟MockRestServiceServer来测试每个人:OperationImplRestTemplate

public class DummyOperationTest {

    private DummyOperation dummyOperation;

    private RestTemplate mockedRestTemplate = mock(RestTemplate.class);


    @Before
    public void setUp() throws Exception {
    super.setUp();
    dummyOperation = new DummyOperationImpl(PLATFORM_BASE_URL, mockedRestTemplate);
    }

    @Test
    public void test() throws Exception {

    String calledUrl = PLATFORM_BASE_URL + "/objects?update_if_exists=true";
    when(mockedRestTemplate.postForObject(calledUrl, expectedSmartObject, SmartObject.class)).thenReturn(expectedSmartObject);

    smartObjectService.create(expectedSmartObject, true);
    verify(mockedRestTemplate, atMost(1)).postForObject(calledUrl, expectedSmartObject, SmartObject.class);


    }
}

不幸的是,这仍然不能测试整个请求的执行。我无法验证 oAuth 身份验证是否已正确添加到标头中,或者服务器响应的转换是否正确。

4

1 回答 1

1

好吧,这是一个嘲笑的问题。我没有正确理解所有内容,但我终于解决了。这是一个显示如何进行的示例:

package com.mnubo.platform.android.sdk.internal;

import android.util.Log;

import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.test.web.client.MockRestServiceServer;

import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.mockito.PowerMockito.whenNew;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;

@RunWith(PowerMockRunner.class)
@PrepareForTest({
        Log.class,
        PlainSocketFactory.class,
        SSLSocketFactory.class,
        HttpComponentsClientHttpRequestFactory.class,
        ConnManagerParams.class,
        AbstractHttpClient.class
})
public class DummyTest {

    private final String USER_ACCESS_TOKEN = "user_token";

    private final PlainSocketFactory mockedPlainSocketFactory = mock(PlainSocketFactory.class);
    private final SSLSocketFactory mockedSSLSocketFactory = mock(SSLSocketFactory.class);
    private final SchemeRegistry mockedSchemeRegistry = mock(SchemeRegistry.class);
    private final DefaultHttpClient mockedHttpClient = mock(DefaultHttpClient.class);
    private final HttpParams mockedHttpParams = mock(HttpParams.class);


    private DummyApiImpl dummyApi = new DummyApiImpl(USER_ACCESS_TOKEN);
    protected MockRestServiceServer mockServer;

    @Before
    public void setUp() throws Exception {
        mockStatic(Log.class);
        mockStatic(PlainSocketFactory.class);
        mockStatic(SchemeRegistry.class);
        mockStatic(SSLSocketFactory.class);
        mockStatic(ConnManagerParams.class);

        whenNew(SchemeRegistry.class).withAnyArguments().thenReturn(mockedSchemeRegistry);
        whenNew(DefaultHttpClient.class).withAnyArguments().thenReturn(mockedHttpClient);
        when(PlainSocketFactory.getSocketFactory()).thenReturn(mockedPlainSocketFactory);
        when(SSLSocketFactory.getSocketFactory()).thenReturn(mockedSSLSocketFactory);
        when(mockedHttpClient.getParams()).thenReturn(mockedHttpParams);

        mockServer = MockRestServiceServer.createServer(dummyApi.getRestTemplate());

    }

    @Test
    public void doOperationTest() throws Exception {

        final User testUser = new User();

        mockUserServiceServer.expect(requestTo(expectedUrl("/users/test")))
                .andExpect(method(POST))
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andRespond(withSuccess());

        dummyApi.userOperations().createUser("test", testUser);
        mockUserServiceServer.verify();
    }
}

调用 Api 的构造函数时出现问题。此类扩展AbstractOAuth2ApiBinding了哪个构造函数创建一个RestTemplate. 这是需要多级模拟的对象。

一旦你模拟了创建所需的元素RestTemplate,剩下的就很容易了,这要感谢模拟服务器!

于 2015-03-17T14:31:41.997 回答