Java 如何使用注释对Spring控制器进行单元测试?

Java 如何使用注释对Spring控制器进行单元测试?,java,spring,spring-mvc,spring-boot,junit,Java,Spring,Spring Mvc,Spring Boot,Junit,我对使用Spring控制器进行单元测试的概念是陌生的。我正在遵循我在网上找到的一些示例,并尝试实施他们的测试策略。这是我的基本控制器: @Controller public class GreetingController { @RequestMapping("/greeting") public String greeting(@RequestParam(value = "name2", required = false, defaultValue = "World2") S

我对使用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也不是GenericXmlWebContextLoader AnnotationConfigWebContextLoader也无法检测默认值,并且 没有为上下文声明ApplicationContextInitializer 配置[ContextConfigurationAttributes@1698539去极化级= 'com.practice.demo.ControllerGreetingTest',位置='{}',类 ='{}',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>

org.springframework.boot
弹簧起动试验
1.5.7.1发布
测试
org.springframework.boot
spring启动程序数据mongodb
org.springframework.boot
弹簧启动装置
org.springframework.boot
弹簧靴开发工具
真的
org.hamcrest
汉克雷斯特酒店
1.3
测试
朱尼特
朱尼特
测试
汉克雷斯特岩芯
org.hamcrest
org.mockito
莫基托磁芯
1.9.5
测试
org.springframework
弹簧试验
3.2.3.1发布
测试
朱尼特
朱尼特
测试
org.mongodb
mongo java驱动程序
3.4.2
org.springframework.boot
spring启动依赖项
1.5.7.1发布
测试

对于带有
org.springframework.boot:springbootstarter测试的项目
可以使用

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

    ...

}

您应该使用
springbootstarter测试
dependency。它有几乎所有的测试

对于测试spring应用程序的控制器部分,您应该为您的测试类使用
@WebMvcTest
注释。使用此注释,spring将仅为控制器部件加载上下文。另外,如果使用此注释,则不需要设置方法。您可以简单地自动连接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
模拟它们,正如您可以看到上面的代码一样

有关spring提供的其他测试片注释,请参见。只需添加注释并引用一个或多个XML配置文件位置或一个或多个配置类。否则,Spring无法自动连接控制器,这需要测试

示例:您想测试一个控制器,该控制器通过@Autowired:

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

如果我们谈论的是spring,请尝试使用@RunWith(SpringRunner.class)boot@Antoniossss我用的是弹簧靴。当我得到一个
无法解析符号'SpringRunner'
org.springframework.boot:springbootstarter时,我应该在pom中包含哪些依赖项来包含SpringRunner.class-test@Antoniossss我似乎无法摆脱这个错误,我附上了我的maven依赖项列表。@Antoniossss我已经解决了关于实现
@RunWith(SpringRunner.class)的问题
但我现在遇到了一个不同的错误:
org.springframework.beans.factory.unsatifiedependencyException:创建名为“com.practice.demo.ControllerGreetingTest”的bean时出错:通过字段“greetingController”表示的未满足的依赖关系。