2012-02-06 207 views
4

這個問題在我問了here的問題旁邊。我正在使用spring-test-mvc框架來測試REST控制器。請參閱上面的鏈接以查看我的REST控制器的代碼。彈簧測試-mvc框架的彈簧REST控制器測試

我的測試GET工作正常,但我不能做POST。當我嘗試這樣做時,我會得到一個例外。這是我第一次測試REST控制器。

這裏是我的PcUserControllerTest類

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:/applicationContextTest.xml") 
public class PcUserControllerTest { 

    @Autowired 
    PcUserService pcUserService; 

    @Autowired 
    PcUserController pcUserController; 

    PcUser pcUser; 

    private MockMvc mockMvc; 

    @Before 
    public void setUp() throws Exception { 
     mockMvc = standaloneSetup(pcUserController).build(); 
     pcUser = new PcUser("John", "Li", "Weasley", "john", "john"); 
     pcUserService.create(pcUser); 
    } 

    @After 
    public void tearDown() throws Exception { 
     pcUserService.delete(pcUser.getId()); 
    } 

    @Test 
    public void shouldGetPcUser() throws Exception { 
     this.mockMvc.perform(get("/pcusers/" + pcUser.getId()).accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); 
    } 

    @Test 
    public void shouldCreatePcUser() throws Exception { 
     PcUser newUser = new PcUser("Mike", "Li", "Donald", "mike", "mike"); 
     this.mockMvc.perform(post("/pcusers/create/" + newUser).accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); 
    } 
} 

例外,我得到當我執行shouldCreatePcUser:

java.lang.IllegalArgumentException: Not enough variable values available to expand ["firstName"] 
    at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:1011) 
    at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:443) 
    at org.springframework.web.util.UriComponents.access$1(UriComponents.java:431) 
    at org.springframework.web.util.UriComponents$FullPathComponent.expand(UriComponents.java:790) 
    at org.springframework.web.util.UriComponents.expandInternal(UriComponents.java:413) 
    at org.springframework.web.util.UriComponents.expand(UriComponents.java:404) 
    at org.springframework.web.util.UriTemplate.expand(UriTemplate.java:121) 
    at org.springframework.test.web.server.request.MockMvcRequestBuilders.expandUrl(MockMvcRequestBuilders.java:51) 
    at org.springframework.test.web.server.request.MockMvcRequestBuilders.request(MockMvcRequestBuilders.java:45) 
    at org.springframework.test.web.server.request.MockMvcRequestBuilders.post(MockMvcRequestBuilders.java:28) 
    at com.project.cleaner.controller.test.PcUserControllerTest.shouldCreatePcUser(PcUserControllerTest.java:69) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

我PcUser看起來像

@Document 
public class PcUser extends BaseEntity { 
    private String firstName; 
    private String middleName; 
    private String lastName; 
    private String username; 
    private String password; 

    public PcUser() { 
     super(); 
    } 

    public PcUser(String firstName, String middleName, String lastName, 
      String username, String password) { 
     super(); 
     this.firstName = firstName; 
     this.middleName = middleName; 
     this.lastName = lastName; 
     this.username = username; 
     this.password = password; 
    } 

    public String getFirstName() { 
     return firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    public String getMiddleName() { 
     return middleName; 
    } 

    public void setMiddleName(String middleName) { 
     this.middleName = middleName; 
    } 

    public String getLastName() { 
     return lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    public String getUsername() { 
     return username; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    @Override 
    public String toString() { 
//  JSONObject jsonPcUser = new JSONObject(); 
//  jsonPcUser.put("id", this.getId()); 
//  jsonPcUser.put("firstName", this.firstName); 
//  jsonPcUser.put("middleName", this.middleName); 
//  jsonPcUser.put("lastName", this.lastName); 
//  jsonPcUser.put("username", this.username); 
// 
//  return jsonPcUser.toJSONString(); 

     return "{\"firstName\":" + this.firstName + ", " 
       + "\"middleName\":" + this.middleName + ", " 
       + "\"lastName\":" + this.lastName + ", " 
       + "\"username\":" + this.username 
       + "}"; 
    } 
} 

BaseEntity:

public class BaseEntity { 
    @Id 
    private String id; 

    public BaseEntity() { 
    } 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 
} 

我不明白這個例外。如果任何人能夠指引我在正確的方向將非常感激。

回答

2

好吧,你有這個作爲你的get

get("/pcusers/" + pcUser.getId()) 

,因爲你想在/pcusers/123/獲取資源這是合理的,但你必須:

PcUser newUser = new PcUser("Mike", "Li", "Donald", "mike", "mike"); 
post("/pcusers/create/" + newUser) 

不真的很有意義,因爲您將在newUser對象上執行toString(),然後將其與/pcusers/create/字符串連接起來。所以你可能正在做一個像/pcusers/create/[email protected]這樣的請求,這可能不是你想要的。

+0

是的,你說得對,toString()方法會被調用。我重寫了toString()方法,它以JSON格式返回數據。這個想法是這樣做的:/ pcusers/create/{firstName:Mike,middleName:Li,lastName:Rubble},當它到達服務器時,它將被轉換成一個PcUser對象。正如我所說這是我第一次玩REST控制器,這是不正確的。我們應該如何在POST中傳遞數據? – jsf 2012-02-06 14:14:01

+2

當然,你在POST中傳遞數據,但不是那樣。它需要位於POST的** body **中,而不是url的一部分。 – beerbajay 2012-02-06 14:33:21

+0

是的,這解決了我的問題並解決了這個問題。非常感謝你的幫助。非常感謝。 – jsf 2012-02-06 17:34:55

3

看起來,正如beerbajay提到的那樣,問題是您要發佈到控制器的是PcUser作爲URL /路徑參數,而不是HTTP請求的實際主體。

我使用org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder#含量(字符串)方法來設置HTTP請求本身的主體(而不是替代URL的部分或添加URL參數)如下:

PcUser newUser = new PcUser("Mike", "Li", "Donald", "mike", "mike"); 
this.mockMvc.perform(post("/pcusers/create/") 
      .content(newUser.toString()) // <-- sets the request content ! 
      .accept(MediaType.APPLICATION_JSON) 
      .andExpect(status().isOk());