[英]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.