简体   繁体   English

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

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

I am new to the concept of unit testing with Spring controllers. 我是Spring控制器单元测试概念的新手。 I'm following some examples I found online and trying to implement their testing strategy. 我正在按照我在网上找到的一些例子来尝试实施他们的测试策略。 This is my basic controller: 这是我的基本控制器:

@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";
    }

}

This is my unit test: 这是我的单元测试:

@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"));
    }

}

Seems pretty straight forward but I get the following error: 看起来非常直接,但我收到以下错误:

java.lang.IllegalStateException: Neither GenericXmlWebContextLoader nor AnnotationConfigWebContextLoader was able to detect defaults, and no ApplicationContextInitializers were declared for context configuration [ContextConfigurationAttributes@1698539 declaringClass = 'com.practice.demo.ControllerGreetingTest', locations = '{}', classes = '{}', inheritLocations = true, initializers = '{}', inheritInitializers = true, name = [null], contextLoaderClass = 'org.springframework.test.context.ContextLoader'] 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']

I'm assuming I have to add a parameter to the @ContextConfiguration annotation but not sure what to include in there. 我假设我必须在@ContextConfiguration注释中添加一个参数,但不知道该包含哪些内容。

EDIT = This is what I have so far: 编辑=这是我到目前为止:

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"));
    }

}

It does the job but it doesn't use any of the Spring annotations like I tried to do before.. this approach is not good so trying to figure out why I keep gettings errors whenever I include the annotations in my test file. 它完成了这项工作,但它没有像我之前尝试过的那样使用任何Spring注释。这种方法并不好,所以试图弄清楚为什么每当我在我的测试文件中包含注释时我都会遇到错误。

My POM: 我的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>

You should use spring-boot-starter-test dependency. 您应该使用spring-boot-starter-test依赖项。 It has almost everything for testing. 它几乎可以用于测试。

And for testing controller part of a spring application, you should use @WebMvcTest annotation for your test class. 为了测试spring应用程序的控制器部分,您应该为测试类使用@WebMvcTest批注。 With this annotation spring will load context just for controller part. 使用此注释弹簧将仅为控制器部件加载上下文。 Plus you don't need to setup method if you use this annotation. 另外,如果使用此注释,则无需设置方法。 You can simply autowire mockMvc. 你可以简单地自动装配mockMvc。 Your test class should be like this: 你的测试类应该是这样的:

@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"));
    }

}

Note: Your controller does not have any autowired fields. 注意:您的控制器没有任何自动装配的字段。 In cases that controller has some autowired objects like service or repository objects. 如果控制器有一些自动对象,如服务或存储库对象。 you can simply mock them with annotation @MockBean as you can see above code. 您可以使用注释@MockBean简单地模拟它们,如上所示。

See this link for other test slice annotations spring provided 请参阅此链接以获取其他测试切片注释弹簧

For projects with org.springframework.boot:spring-boot-starter-test can use 对于使用org.springframework.boot:spring-boot-starter-test项目org.springframework.boot:spring-boot-starter-test可以使用

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

Where App.class is you main application class annotated with @SpringBootApplication . 其中App.class是使用@SpringBootApplication注释的主应用程序类。 But you better read the documentation . 但是你最好阅读文档 And if you don't want to include (classes = App.class) part you also can change folder structure 如果您不想包含(classes = App.class)部分,您还可以更改文件夹结构

For simple controllers it is possible to perform simple standalone tests 对于简单的控制器,可以执行简单的独立测试

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

    ...

}

Just add the @ContextConfiguration annotation and refer one or more XML configuration file locations or one or more configuration classes. 只需添加@ContextConfiguration批注并引用一个或多个XML配置文件位置或一个或多个配置类。 Otherwise Spring cannot autowire your controller, which should be tested. 否则Spring无法对您的控制器进行自动装配,应对其进行测试。

Example: You want to test a controller, which uses MyService via @Autowired: 示例:您想要测试一个控制器,它通过@Autowired使用MyService:

MyControllerTest : Injects the controller, which should be tested using the MyTestConfig configuration class. 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 : Returns all beans, which are required for the test. MyTestConfig :返回测试所需的所有bean。 Use Mockito to mock the depedencies of your controller, because we want to test only the controller and not the service layer. 使用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.

相关问题 如何在 @ComponentScan @Configuration 中使用数据源依赖项对 Spring 引导应用程序的 controller 进行单元测试 - How do I unit-test the controller of a Spring Boot application with a DataSource dependency in a @ComponentScan @Configuration 如何使用@PathVariable对Spring MVC控制器进行单元测试? - How to unit test a Spring MVC controller using @PathVariable? 如何使用Spring Security对Spring 4 DAO方法进行单元测试? - How do I unit test a Spring 4 DAO method with Spring Security? 使用Jmockit的单元测试Spring MVC控制器 - Unit Test Spring MVC Controller Using Jmockit 如何使用Junit和Mockito对REST控制器进行单元测试? - How do I unit test my REST Controller using Junit and Mockito? 如何在 Spring Boot 中为控制器编写单元测试 - How to write unit test for controller in spring boot 如何对Spring MVC带注释的控制器进行单元测试? - How to unit test a Spring MVC annotated controller? 如何使用注解将Spring安全性配置为在处女座上工作? - How do I configure Spring security to work on Virgo - using annotations? 如何在Spring中使用注释定义PasswordEncoder? - How do I define a PasswordEncoder using annotations in Spring? 如何在 Spring 单元测试中重新启动关闭的 EmbeddedKafkaServer? - How do I Restart a shutdown embeddedKafkaServer in a Spring Unit Test?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM