use*_*753 5 spring spring-mvc spring-boot
这让我在努力让 spring boot @configurationproperties 注释工作起来。所以希望有人能为我阐明我做错了什么。我有一个 Spring Boot 应用程序,它在类路径上包含一个 application.properties 。它的价值在于
server.contextPath=/test/v1
server.port=8080
spring.profiles.active=dev
vendors=me
Run Code Online (Sandbox Code Playgroud)
我有一个 application.class ,它具有 spring boot 注释,位于包层次结构的顶部
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableConfigurationProperties
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试将属性供应商映射到配置属性 bean 中,如下所示
package com.test.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("classpath:application.properties")
@ConfigurationProperties
public class GlobalProperties {
private String vendors;
public String getVendors() {
return vendors;
}
public void setVendors(String vendors) {
this.vendors = vendors;
}
}
Run Code Online (Sandbox Code Playgroud)
然后从我的休息控制器调用这个bean。我知道它解析了该属性,因为当我重命名它时,服务器无法启动。在下面的代码中,props bean 没有自动装配并且为 null。//为简洁起见省略代码
package com.test.controller;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.test.config.GlobalProperties;
@RestController
@Component
public class MController {
//TODO should be wired in from properties file
@Autowired
GlobalProperties props;
private boolean vendorUnknown(String vendor) {
if(props.getAllowedVendor().equalsIgnoreCase(vendor)) {
return true;
}
return false;
}
@RequestMapping(value = "/test/{id}", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<?> getStatus(
@PathVariable String id) {
//@RequestBody Bookmark input
if(vendorUnknown("me")) {
System.out.println("found");
};
return ResponseEntity.noContent().build();
}
}
Run Code Online (Sandbox Code Playgroud)
有人请指出我做错了什么吗?
更新:
将上面的代码更改为更简单的版本,并使用测试类来重现问题。请参阅下面的我的 pom.xml 和测试类
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.me.test</groupId>
<artifactId>test-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- tag::actuator[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- end::actuator[] -->
<!-- tag::tests[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- end::tests[] -->
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Run Code Online (Sandbox Code Playgroud)
测试类:
package com.test.controller;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MControllerTest {
@Autowired
private MockMvc mockMvc;
@InjectMocks
MController testController;
@Before
public void setup() {
// this must be called for the @Mock annotations above to be processed
// and for the mock service to be injected into the controller under
// test.
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(testController).build();
}
@Test
public void testPropertiesMsg() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/test/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
}
Run Code Online (Sandbox Code Playgroud)
@PropertySource。您可以保留@Component,如果不保留,请指定@EnableConfigurationProperties(GlobalProperties.class)。@Component上testController。但我认为你的问题是你vendorUnknown从哪里调用方法。它没有显示在您的代码中。如果从构造函数调用,则 bean 初始化尚未完成,并且GlobalProperties props确实为 null。编辑:
根据OP的编辑,这是一个完全有效的解决方案。
演示应用程序.java:
@SpringBootApplication
@EnableConfigurationProperties
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
演示控制器.java:
@RestController
public class DemoController {
@Autowired
private DemoProperties props;
@GetMapping(value = "/", produces = APPLICATION_JSON_VALUE)
public ResponseEntity<?> getVendor() {
return ResponseEntity.ok(props.getVendors());
}
}
Run Code Online (Sandbox Code Playgroud)
演示属性.java:
@ConfigurationProperties
@Component
public class DemoProperties {
private String vendors;
public String getVendors() {
return vendors;
}
public void setVendors(String vendors) {
this.vendors = vendors;
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序属性:
vendors=me
Run Code Online (Sandbox Code Playgroud)
DemoControllerTest.java:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DemoControllerTest {
@Autowired
TestRestTemplate restTemplate;
@Test
public void testGenVendor() throws Exception {
String vendor = restTemplate.getForObject("/", String.class);
assertThat(vendor).isEqualTo("me");
}
}
Run Code Online (Sandbox Code Playgroud)
OP代码的问题:
MockMvc不使用主类,因此EnableConfigurationProperties不进行处理。MockMvc或者WebMvcTest旨在测试 Web 层(废话!),而不是整个应用程序。使用其中任何一个。bean 的属性应该由测试来设置。
InjectMocks失败无声无息。了解为什么不应使用 InjectMocks 注释来自动装配字段。
| 归档时间: |
|
| 查看次数: |
27497 次 |
| 最近记录: |