2014-09-24 114 views
1

我正在使用Powermock爲澤西Web服務構建測試用例,我試圖模擬數據庫函數調用,專門用於PUT和POST調用。但是,我遇到問題需要解決。嘲笑私有無效方法給出AssertionError

這裏是Web服務調用的一個樣子:

@Path("/v1.0.0") 
public class WebService { 

    @POST 
    @Path("application") 
    @Consumes(MediaType.APPLICATION_JSON) 
    public Response createApplication(@QueryParam("callback") String callbackFunction, String body) 
      throws NamingException, SQLException, IllegalStateException, CacheException, UnknownHostException, 
      IOException { 
     String query = "exec spInsertApplication ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?"; 
     String[] params = new String[16]; 
     JSONObject json = (JSONObject) JSONValue.parse(body); 
     params[0] = json.get("name").toString(); 
     params[4] = json.get("software").toString(); 
     params[14] = json.get("customerid").toString(); 
     //Null checks for other params 

     runUpdateQuery(query, params); 

     return generateResponse(callbackFunction, null); 
    } 

    private void runUpdateQuery(String query, String[] queryParameters) { 
     //Handles running DB query 
    } 
} 

什麼我測試的情況下目前的樣子:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(WebService.class) 
@PowerMockIgnore({"javax.management.*"}) 
public class TestRestWebService { 

    @Test 
    public void test_createApplication_returns_http_success() throws Exception { 
     String query = "exec spInsertApplication ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?"; 
     String[] params = new String[16]; 
     params[0] = "test_app_name"; 
     params[4] = "test_software"; 
     params[14] = "23"; 

     WebService tested = createPartialMockAndInvokeDefaultConstructor(WebService.class, "runUpdateQuery"); 
     expectPrivate(tested, "runUpdateQuery", query, params).andAnswer(
       new IAnswer<Void>() { 
        @Override 
        public Void answer() throws Throwable { 
         return null; 
        } 
       }); 
     replay(tested); 

     String JSONString = "{\"name\":\"test_service_name\",\"software\":\"test_software\",\"customerid\":\"23\"}"; 
     Response output = tested.createApplication("CALLBACK", JSONString); 
     verify(tested); 
     assertTrue(output.getStatus() == 200); 
    } 
} 

在運行時,這是給我一個AssertionError說:

意外的方法調用WebService.runUpdateQuery(「exec spInsertApplication?,?,?,? ,?,?,?,?,?,?,?,?,?, ?,?,?「,[」test_service_name「,null,null,」test_software「, null,null, ,null,null,null,null,「23」,null]):

WebService.runUpdateQuery(「exec spInsertApplication?,?,?, ?,?,?,?,?,?,? ,?,?,?,?,?,?「,[」test_service_name「,null, null,null,」test_software「,null,null,null,null,null,null, null, 23,null]):預計:1,實際:0

經過多一點挖掘後,我發現原因很可能與PowerMock如何比較字符串a rrays。所以我也試着用更通用的方法,因爲函數返回void無效,通過使用EasyMock.anyString()EasyMock.isA(String[].class)來代替我的兩個參數,但是這會導致NullPointerException。下面是堆棧跟蹤的前幾行:

java.lang.NullPointerException 
    at java.lang.Class.isAssignableFrom(Native Method) 
    at org.powermock.reflect.internal.WhiteboxImpl.checkIfParameterTypesAreSame(WhiteboxImpl.java:2432) 
    at org.powermock.reflect.internal.WhiteboxImpl.getMethods(WhiteboxImpl.java:1934) 
    at org.powermock.reflect.internal.WhiteboxImpl.getBestMethodCandidate(WhiteboxImpl.java:1025) 
    at org.powermock.reflect.internal.WhiteboxImpl.findMethodOrThrowException(WhiteboxImpl.java:948) 

我如何去正確地嘲諷這種私人無效的方法,以避免我的測試過程中調用數據庫?

回答

1

通過這次測試和文檔挖掘了幾次後,我發現expectPrivate調用沒有找到我的方法。因此,這裏是我發現我可以指定功能:

expectPrivate(tested, WebService.class.getDeclaredMethod("runUpdateQuery", String.class, String[].class), 
     EasyMock.anyString(), EasyMock.aryEq(params)).andAnswer(new IAnswer<Void>() { 
    @Override 
    public Void answer() throws Throwable { 
     return null; 
    } 
}); 

這也讓我做的陣列的比較調用函數像我本來想同時使用泛型類型定義的功能。