繁体   English   中英

如何使用注释对Spring Controller进行单元测试?

[英]How do I unit test Spring Controller using annotations?

我是Spring控制器单元测试概念的新手。 我正在按照我在网上找到的一些例子来尝试实施他们的测试策略。 这是我的基本控制器:

@Controller
public class GreetingController {

    @RequestMapping("/greeting")
    public String greeting(@RequestParam(value = "name2", required = false, defaultValue = "World2") String name2,
                           Model model) {

        model.addAttribute("name", name2);
        return "greeting";
    }

}

这是我的单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class ControllerGreetingTest {

    private MockMvc mockMvc;

    @Autowired
    GreetingController greetingController;
    @Test
    public void shouldReturnSomething() throws Exception {
        mockMvc.perform(get("/greeting"))
                .andExpect(status().isOk())
                .andExpect(view().name("greeting"));
    }

}

看起来非常直接,但我收到以下错误:

java.lang.IllegalStateException:GenericXmlWebContextLoader和AnnotationConfigWebContextLoader都没有能够检测默认值,也没有为上下文配置声明ApplicationContextInitializers [ContextConfigurationAttributes @ 1698539 declaringClass ='com.practice.demo.ControllerGreetingTest',locations ='{}',classes =' {}',inheritLocations = true,initializers ='{}',inheritInitializers = true,name = [null],contextLoaderClass ='org.springframework.test.context.ContextLoader']

我假设我必须在@ContextConfiguration注释中添加一个参数,但不知道该包含哪些内容。

编辑=这是我到目前为止:

public class ControllerGreetingTest {

    private MockMvc mockMvc;

   @Before
    public void setup(){
        this.mockMvc = standaloneSetup(new GreetingController()).build();
    }

    @Test
    public void shouldReturnDefaultString() throws Exception {
        mockMvc.perform(get("/greeting"))
                .andExpect(status().isOk())
                .andExpect(view().name("greetings"))
                .andExpect(model().attribute("name","World2"));
    }

}

它完成了这项工作,但它没有像我之前尝试过的那样使用任何Spring注释。这种方法并不好,所以试图弄清楚为什么每当我在我的测试文件中包含注释时我都会遇到错误。

我的POM:

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>1.5.7.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-all</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <artifactId>hamcrest-core</artifactId>
                <groupId>org.hamcrest</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>1.9.5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>3.2.3.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>3.4.2</version>
        </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>1.5.7.RELEASE</version>
        <scope>test</scope>
    </dependency>

</dependencies>

您应该使用spring-boot-starter-test依赖项。 它几乎可以用于测试。

为了测试spring应用程序的控制器部分,您应该为测试类使用@WebMvcTest批注。 使用此注释弹簧将仅为控制器部件加载上下文。 另外,如果使用此注释,则无需设置方法。 你可以简单地自动装配mockMvc。 你的测试类应该是这样的:

@RunWith(SpringRunner.class)
@WebMvcTest(GreetingController.class)
public class ControllerGreetingTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private SomeServiceClass someServiceClass;

    @Test
    public void shouldReturnDefaultString() throws Exception {
        mockMvc.perform(get("/greeting"))
            .andExpect(status().isOk())
            .andExpect(view().name("greetings"))
            .andExpect(model().attribute("name","World2"));
    }

}

注意:您的控制器没有任何自动装配的字段。 如果控制器有一些自动对象,如服务或存储库对象。 您可以使用注释@MockBean简单地模拟它们,如上所示。

请参阅此链接以获取其他测试切片注释弹簧

对于使用org.springframework.boot:spring-boot-starter-test项目org.springframework.boot:spring-boot-starter-test可以使用

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class ControllerGreetingTest {
    ...
}

其中App.class是使用@SpringBootApplication注释的主应用程序类。 但是你最好阅读文档 如果您不想包含(classes = App.class)部分,您还可以更改文件夹结构

对于简单的控制器,可以执行简单的独立测试

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = ControllerGreeting.class)
public class ControllerGreetingTest {
    @Autowired
    private MockMvc mockMvc;

    ...

}

只需添加@ContextConfiguration批注并引用一个或多个XML配置文件位置或一个或多个配置类。 否则Spring无法对您的控制器进行自动装配,应对其进行测试。

示例:您想要测试一个控制器,它通过@Autowired使用MyService:

MyControllerTest :注入控制器,应使用MyTestConfig配置类进行测试。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyTestConfig.class})
@WebAppConfiguration
public class MyControllerTest {

  private MockMvc mockMvc;

  @Autowired
  private MyController controller;

  @Before
  public void setUp() {
    mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
  }

  // Tests
}

MyTestConfig :返回测试所需的所有bean。 使用Mockito来模拟控制器的依赖性,因为我们只想测试控制器而不是服务层。

@Configuration
public class MyTestConfig {

  @Bean
  public MyService myService() {
    return Mockito.mock(MyService.class);
  }

  @Bean
  public MyController myController() {
    return new MyController();
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM