2015-02-24 55 views
1

我使用Spring的Android休息模板來執行HTTP請求使用MockRestServiceServer與構建工具。我正在測試像這樣:Android的彈簧安置模板1.1

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但後來我不得不嘲笑SchemeRegistry的register方法是隻在本地訪問從構造函數(source)。

所以我放棄了試圖嘲笑一切詭計的RestTemplate內發生的事情,並決定直接嘲笑RestTemplate。

我需要幫助來正確地模擬它,以便MockRestServiceServer仍然可以在我的測試中使用,因爲現在,myapiMockServer.verify()斷言失敗。

更新 我仍然無法使用MockRestServiceServer來測試我的API,但我設法測試每個個體OperationImpl使用的RestTemplate像這樣一個模擬:

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身份驗證是否已正確添加到標頭,或者服務器響應的轉換是否正確。

回答

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("https://stackoverflow.com/users/test"))) 
       .andExpect(method(POST)) 
       .andExpect(content().contentType(MediaType.APPLICATION_JSON)) 
       .andRespond(withSuccess()); 

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

當調用Api的構造函數時發生問題。這個類擴展了AbstractOAuth2ApiBinding,這個構造函數創建了一個RestTemplate。這是需要多層次嘲笑的這個對象。

一旦你嘲笑所需的元素創建RestTemplate,其餘的是很容易的,感謝模擬服務器!