测试一个spring mvc rest控制器

Posted

技术标签:

【中文标题】测试一个spring mvc rest控制器【英文标题】:Testing a spring mvc rest controller 【发布时间】:2016-02-08 04:42:37 【问题描述】:

我正在尝试使用 MockMvcBuilders.standaloneSetup 方法为 spring mvc 休息控制器创建一个非常基本的单元测试。我不断收到 404 错误。下面我列出了我的测试应用程序上下文、我的测试类、我的控制器和完整的堆栈跟踪。任何指导表示赞赏。

@Configuration
public class TestContext

    @Bean
    public Service service()
    
        return mock(Service.class);
    


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=TestContext.class)
@WebAppConfiguration
public class TestUsingWebAppContextSetUp

    private MockMvc mockMvc;

    @Autowired
    private Service service;

    @Before
    public void setUp()
    
        mockMvc = MockMvcBuilders.standaloneSetup(MyController.class)
                .build();
    

    @Test
    public void test() throws Exception
    
        mockMvc.perform(get("/search?phoneNumber=5551112222"))
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE));
    


public class MyController

    @Autowired
    private Service service;

    @RequestMapping("/search")
    public List<SearchResult> search(@RequestParam(value="phoneNumber") String phoneNumber)
    
        System.out.println("search called");
        Search search = new Search();
        search.setPhoneNumber(phoneNumber);
        return service.search(search);
    

java.lang.AssertionError:预期状态: 但原为: org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60) 在 org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89) 在 org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:653) 在 org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:152) 在 com.mycompany.TestUsingWebAppContextSetUp.test(TestUsingWebAppContextSetUp.java:41) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)在 java.lang.reflect.Method.invoke(未知来源)在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73) 在 org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) 在 org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73) 在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:217) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 在 org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 在 org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

【问题讨论】:

【参考方案1】:

MockMvcBuilders.standaloneSetup 状态的 javadoc

通过注册一个或多个@Controller实例来构建MockMvc 和 以编程方式配置 Spring MVC 基础结构。这允许 完全控制控制器的实例化和初始化, 及其依赖项,类似于普通的单元测试,同时也使 一次可以测试一个控制器。

所以你会使用它

mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();

注册一个实际的实例。如果您需要将其作为 Spring 托管实例(您可能确实认为它有一个 @Autowired 字段),您必须从 ApplicationContext 获取它。

【讨论】:

那行得通。我现在在那里放了一个包可见的设置器,这样我就可以注入服务了。我会尝试让上下文版本在某个时候运行。谢谢! 我想知道如果他们希望你实例化一个类,为什么他们有一个方法签名呢?方法签名意味着他们实例化并配置它。 @JoshChappelle 公平地说,该方法的参数类型为Object。由于没有“Controller”超类型,Spring 必须接受所有可能被 @Controller 注释的类型。 啊,没想到。当我发表评论时,我面前没有代码。现在我只能责怪自己了。 :-) 再次感谢。

以上是关于测试一个spring mvc rest控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何访问 Spring MVC REST 控制器中的 HTTP 标头信息?

如何在 spring-mvc 中为 REST 查询提供对象列表?

Spring MVC 转换 Spring Rest Api

混合 Spring MVC + Spring Data Rest 会导致奇怪的 MVC 响应

从 Spring MVC 控制器自动生成 REST api 文档到 RAML

REST - 使用 Spring MVC 返回创建的对象