文章整理来源:Spring编程常见错误50例_spring_spring编程_bean_AOP_SpringCloud_SpringWeb_测试_事务_Data-极客时间
1. 定义 Controller ,2. 定义 HelloWorldService,3 在 /src/main/resource 下定义 spring.xml 文件,4. 定义 Configuration 引入 spring.xml 文件,5. 定义 SpringTest
// 1. 步骤 1
@RestController
public class HelloController {
@Autowired
HelloWorldService helloWorldService;
@RequestMapping(path = "hi", method = RequestMethod.GET)
public String hi() throws Exception{
return helloWorldService.toString() ;
};
}
-----------------------------------------------
// 2. 步骤 2
public class HelloWorldService {
}
-----------------------------------------------
// 3. 步骤 3
{"""
"""}
------------------------------------------------
// 4. 步骤 4
@Configuration
@ImportResource(locations = {"spring.xml"})
public class Config {
}
------------------------------------------------
// 5. 步骤 5
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyTestApplication.class)
public class TestApplication {
@Autowired
HelloController helloController;
@Test
public void testController() throws Exception {
String response = helloController.hi();
Assert.notNull(response, "not null");
}
}
程序抛出找不到 spring.xml 文件错误
解析:1. 普通的启动程序使用的是 ClassPathResource#getInputStream 来加载 spring.xml 文
2. 测试程序使用的是 MockServletContext#getResourceAsStream 来加载文件 spring.xml,而它会从 SpringBootMockServletContext#getResourceLocation() 方法中提供的路径去尝试加载文件
protected String getResourceLocation(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
//加上前缀:/src/main/resources
String resourceLocation = this.getResourceBasePathLocation(path);
if (this.exists(resourceLocation)) {
return resourceLocation;
} else {
//{"classpath:META-INF/resources", "classpath:resources", "classpath:static", "classpath:public"};
String[] var3 = SPRING_BOOT_RESOURCE_LOCATIONS;
int var4 = var3.length;
for(int var5 = 0; var5 < var4; ++var5) {
String prefix = var3[var5];
resourceLocation = prefix + path;
if (this.exists(resourceLocation)) {
return resourceLocation;
}
}
return super.getResourceLocation(path);
}
}
它尝试从下面的一些位置进行加载:
classpath:META-INF/resources
classpath:resources
classpath:static
classpath:public
src/main/webapp
而程序编译启动后的目录如下,从上面提供的路径中找不到 spring.xml
解决: 1. 建立一个 src/main/webapp,然后把 spring.xml 放入
2. 在 /src/main/resources 下面再建立一个 resources 目录,然后放入 spring.xml
3. 在 @ImportResource 使用 classpath 加载方式
@Configuration
//@ImportResource(locations = {"spring.xml"})
@ImportResource(locations = {"classpath:spring.xml"})
public class Config {
}
1. 定义被测试类和对应的测试程序
@Service
public class ServiceOne {
}
@Service
public class ServiceTwo {
}
---------------------------------
@SpringBootTest()
class ServiceOneTests {
@MockBean
ServiceOne serviceOne;
@Test
public void test(){
System.out.println(serviceOne);
}
}
@SpringBootTest()
class ServiceTwoTests {
@MockBean
ServiceTwo serviceTwo;
@Test
public void test(){
System.out.println(serviceTwo);
}
}
解析:正常情况是不会重新创建一个 Spring Context 的。这是因为 Spring Test 使用了 Context 的缓存以避免重复创建 Context
而 @MockBean 的使用会导致 TestContext 生成上下文的 Cache Key 变得不同
解决:把相关的 MockBean 定义放到一个地方里
public class ServiceTests {
@MockBean
ServiceOne serviceOne;
@MockBean
ServiceTwo serviceTwo;
}
@SpringBootTest()
class ServiceOneTests extends ServiceTests{
@Test
public void test(){
System.out.println(serviceOne);
}
}
@SpringBootTest()
class ServiceTwoTests extends ServiceTests{
@Test
public void test(){
System.out.println(serviceTwo);
}
}