使用spring-test-mvc框架进行Spring REST控制器测试

时间:2012-02-06 04:19:39

标签: spring testing rest

这个问题紧挨着我提出的问题here。我正在使用 spring-test-mvc 框架来测试 REST 控制器。请参阅上面的链接,查看我的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 个答案:

答案 0 :(得分:3)

正如beerbajay所提到的那样,问题在于您尝试发布到控制器的是PcUser作为URL /路径参数而不是HTTP请求的实际主体。

我正在使用 org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder #content(String)方法设置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());

答案 1 :(得分:2)

好的,您已将此作为get

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

这是有道理的,因为你想要获得/pcusers/123/的资源,但是你有:

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

由于您将在toString()对象上执行newUser,然后将其与/pcusers/create/字符串连接,因此这没有任何意义。所以你可能会对/pcusers/create/com.mycompany.PcUser@1596138这样的事情提出要求,这可能不是你想要的。