Spring TestContext测试框架
详解SpringMVC如何测试Controller(使用springmvcmock测试)

详解SpringMVC如何测试Controller(使⽤springmvcmock测试)在springmvc中⼀般的测试⽤例都是测试service层,今天我来演⽰下如何使⽤springmvc mock直接测试controller层代码。
1.什么是mock测试?mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,⽤⼀个虚拟的对象来创建以便测试的测试⽅法。
2.为什么要使⽤mock测试?使⽤Mock O bject进⾏测试,主要是⽤来模拟那些在应⽤中不容易构造(如HttpServletRequest必须在Servlet容器中才能构造出来)或者⽐较复杂的对象(如JDBC中的ResultSet对象)从⽽使测试顺利进⾏的⼯具。
3.常⽤注解RunWith(SpringJUnit4ClassRunner.class): 表⽰使⽤Spring Test组件进⾏单元测试;WebAppConfiguratio: 使⽤这个annotation会在跑单元测试的时候真实的启⼀个web服务,然后开始调⽤Controller的Rest API,待单元测试跑完之后再将web服务停掉;ContextConfiguration: 指定Bean的配置⽂件信息,可以有多种⽅式,这个例⼦使⽤的是⽂件路径形式,如果有多个配置⽂件,可以将括号中的信息配置为⼀个字符串数组来表⽰;4.安装测试环境spring mvc测试框架提供了两种⽅式,独⽴安装和集成Web环境测试(此种⽅式并不会集成真正的web环境,⽽是通过相应的Mock API进⾏模拟测试,⽆须启动服务器)。
独⽴安装测试⽅式MockMvcBuilders.standaloneSetup(Object... controllers):通过参数指定⼀组控制器,这样就不需要从上下⽂获取了;主要是两个步骤:(1)⾸先⾃⼰创建相应的控制器,注⼊相应的依赖(2)通过MockMvcBuilders.standaloneSetup模拟⼀个Mvc测试环境,通过build得到⼀个MockMvc代码如下:package com.xfs.test;import org.junit.Assert;import org.junit.Before;import org.junit.Test;import org.springframework.test.web.servlet.MockMvc;import org.springframework.test.web.servlet.MvcResult;import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;import org.springframework.test.web.servlet.result.MockMvcResultHandlers;import org.springframework.test.web.servlet.result.MockMvcResultMatchers;import org.springframework.test.web.servlet.setup.MockMvcBuilders;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.xfs.web.controller.APIController;/*** 独⽴安装测试⽅式 springmvc mock测试** @author admin** 2017年11⽉23⽇上午10:39:49*/public class TestApiOne {private MockMvc mockMvc;@Beforepublic void setUp() {APIController apiController = new APIController();mockMvc = MockMvcBuilders.standaloneSetup(apiController).build();}@Testpublic void testGetSequence() {try {MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/api/getSequence")).andExpect(MockMvcResultMatchers.status().is(200)).andDo(MockMvcResultHandlers.print()).andReturn();int status = mvcResult.getResponse().getStatus();System.out.println("请求状态码:" + status);String result = mvcResult.getResponse().getContentAsString();System.out.println("接⼝返回结果:" + result);JSONObject resultObj = JSON.parseObject(result);// 判断接⼝返回json中success字段是否为trueAssert.assertTrue(resultObj.getBooleanValue("success"));} catch (Exception e) {e.printStackTrace();}}}请求结果如下:集成Web环境⽅式MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下⽂获取相应的控制器并得到相应的MockMvc;主要是三个步骤:(1)@WebAppConfiguration:测试环境使⽤,⽤来表⽰测试环境使⽤的ApplicationContext将是WebApplicationContext类型的;value指定web应⽤的根(2)通过@Autowired WebApplicationContext wac:注⼊web环境的ApplicationContext容器(3)然后通过MockMvcBuilders.webAppContextSetup(wac).build()创建⼀个MockMvc进⾏测试代码如下:package com.xfs.test;import org.junit.Assert;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.mock.web.MockHttpSession;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;import org.springframework.test.context.web.WebAppConfiguration;import org.springframework.test.web.servlet.MockMvc;import org.springframework.test.web.servlet.MvcResult;import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;import org.springframework.test.web.servlet.result.MockMvcResultHandlers;import org.springframework.test.web.servlet.result.MockMvcResultMatchers;import org.springframework.test.web.servlet.setup.MockMvcBuilders;import org.springframework.web.context.WebApplicationContext;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;/*** 集成Web环境⽅式 springmvc mock测试** @author admin** 2017年11⽉23⽇上午11:12:43*/@RunWith(JUnit4ClassRunner.class)@WebAppConfiguration@ContextConfiguration(locations = { "classpath*:spring/*.xml" })public class TestApiTwo extends AbstractJUnit4SpringContextTests {@Autowiredpublic WebApplicationContext wac;public MockMvc mockMvc;public MockHttpSession session;@Beforepublic void before() throws Exception {mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();}@Testpublic void testGetSequence() {try {MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/api/getSequence")).andExpect(MockMvcResultMatchers.status().is(200)).andDo(MockMvcResultHandlers.print()).andReturn();int status = mvcResult.getResponse().getStatus();System.out.println("请求状态码:" + status);String result = mvcResult.getResponse().getContentAsString();System.out.println("接⼝返回结果:" + result);JSONObject resultObj = JSON.parseObject(result);// 判断接⼝返回json中success字段是否为trueAssert.assertTrue(resultObj.getBooleanValue("success"));} catch (Exception e) {e.printStackTrace();}}}运⾏结果和上⾯独⽴测试时候⼀样。
使用Eclipse开发基于SpringBoot+JAX-RS的Restful服务

一.搭建工程(开发环境JDK1.8,外置Tomcat需8.5以上版本)1.新建maven项目2.修改pom文件,内容如下:<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance" xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>springboot.jaxrs</groupId><artifactId>RestWS</artifactId><version>0.0.1-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.0.RELEASE</version></parent><dependencies><!-- Web应用依赖:主要用来进行Web应用开发 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- 排除Web依赖提供的Tomcat容器,由下面的Tomcat依赖提供Tomcat容器 --><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><!-- 模板引擎依赖:主要用来提供@Controller和html页面等的访问 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- RESTful服务依赖:主要用来提供Jersey RESTful Web服务框架的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jersey</artifactId></dependency><!-- Tomcat容器依赖:主要用来提供编译和测试时的Tomcat支持,打war包时不会包含到lib --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope></dependency><!-- 测试组件依赖:用来提供单元测试的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><!-- 排除JUnit4的包,只引入JUnit5的包 --><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><build><!-- 打包后的文件名 --><finalName>springboot</finalName><plugins><!-- SpringBoot打包插件,指定main方法的类 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.springboot.SpringBootRun</mainClass> </configuration></plugin></plugins></build></project>3.新建一个springboot.jaxrs的包,并建一个SpringBootRun类package springboot.jaxrs;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder;importorg.springframework.boot.web.servlet.support.SpringBootServletInitializer;@SpringBootApplicationpublic class SpringBootRun extends SpringBootServletInitializer {//通过外置Tomcat启动SpringBoot项目@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {// TODO Auto-generated method stubreturn builder.sources(SpringBootRun.class);}//通过内置Tomcat启动SpringBoot项目public static void main(String[] args) {SpringApplication.run(SpringBootRun.class, args);}}4.新建一个RestConfig类package springboot.jaxrs;import javax.ws.rs.ApplicationPath;import org.glassfish.jersey.server.ResourceConfig;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.cors.CorsConfiguration;import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter;@Configuration@ApplicationPath("/services")public class RestConfig extends ResourceConfig {//注册服务public RestConfig() {//1.自动扫描com.springboot下面的服务packages("springboot.jaxrs");//2.手动注册服务//register(HelloWorldService.class);//register(TestService.class);System.out.println("WADL地址:http://localhost:8080/RestWS/services/application.wadl");}//添加跨域访问服务:只开放了WS访问,没有开放@Controller访问@Beanpublic CorsFilter corsFilter() {CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/ws/**", corsConfiguration); // 4 设置允许访问的地址过滤return new CorsFilter(source);}}5.新建一个springboot.jaxrs.controller的包,并建一个PagesController类package springboot.jaxrs.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;@CrossOrigin(origins = "*",maxAge = 3600)//如果想让@Controller允许跨域访问可以加上@CrossOrigin@Controller@RequestMapping("/pages")public class PagesController {@ResponseBody@RequestMapping(value = "/say", method = RequestMethod.GET)public String index() {return"Hello World";}@RequestMapping("/main")public String mainPage() {return"main";}}6.新建一个springboot.jaxrs.entity的包,并新建User类package springboot.jaxrs.entity;public class User {private String name;//姓名private String idNo;//身份证private String password;//密码public User(String name,String idNo,String password) { = name;this.idNo = idNo;this.password = password;}//重写HashCode方法,让程序判断身份证号码相同为同一个对象@Overridepublic int hashCode() {// TODO Auto-generated method stubreturn idNo.hashCode();}//重写equals方法,让程序判断身份证号码相同为同一个对象@Overridepublic boolean equals(Object obj) {// TODO Auto-generated method stubif(obj instanceof User){User user = (User) obj;return this.idNo.equals(user.getIdNo());}else {return false;}}@Overridepublic String toString() {// TODO Auto-generated method stubreturn"[name:"+name+",idNo:"+idNo+",password:"+password+"]";}public String getName() {return name;}public String getIdNo() {return idNo;}public void setIdNo(String idNo) {this.idNo = idNo;}public void setName(String name) { = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}7.新建一个springboot.jaxrs.webservice包并新建UsersService类package springboot.jaxrs.webservice;import java.util.HashMap;import java.util.Map;import javax.inject.Singleton;import javax.ws.rs.Consumes;import javax.ws.rs.DELETE;import javax.ws.rs.GET;import javax.ws.rs.POST;import javax.ws.rs.PUT;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;import javax.ws.rs.core.Response;import javax.ws.rs.core.Response.Status;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import er;@Path("/ws/users")@Singleton//设置为单例,要不然userMap每次都会new一个新的public class UsersService {Map<String,User> userMap = new HashMap<>();@GET@Path("/getAllUser")@Produces(value=MediaType.APPLICATION_JSON) //JSON方式返回public Response getAllUser() {try {String userJson = new ObjectMapper().writeValueAsString(userMap);return Response.status(Status.OK).entity(userJson).build();} catch (JsonProcessingException e) {// TODO Auto-generated catch blocke.printStackTrace();returnResponse.status(Status.OK).entity("{\"error\":\""+e.toString()+"\"}").build();}}@GET@Path("/{userid}/get")@Consumes(value=MediaType.APPLICATION_JSON) //JSON方式接受请求@Produces(value=MediaType.APPLICATION_JSON) //JSON方式返回public Response getById(@PathParam("userid") String userid) {try {String userJson = newObjectMapper().writeValueAsString(userMap.get(userid));return Response.status(Status.OK).entity(userJson).build();} catch (JsonProcessingException e) {// TODO Auto-generated catch blocke.printStackTrace();returnResponse.status(Status.OK).entity("{\"error\":\""+e.toString()+"\"}").build();}}@POST@Path("/{userid}/update")public Response update(@PathParam("userid") String userid, User user) { if(user.getName()!=null)userMap.get(userid).setName(user.getName());//if(user.getIdNo()!=null)//userMap.get(userid).setIdNo(user.getIdNo());if(user.getPassword()!=null)userMap.get(userid).setPassword(user.getPassword());String output = userid + " 属性修改成功!";return Response.status(Status.OK).entity(output).build();}@PUT@Path("/{userid}/addOrReplace")@Consumes(value=MediaType.APPLICATION_JSON) //JSON方式接受请求@Produces(value=MediaType.TEXT_PLAIN) //纯文本方式返回public Response addOrReplace(@PathParam("userid") String userid, User user) { try {userMap.put(userid,user);return Response.status(Status.OK).entity("增添用户成功,用户信息:"+user.toString()).build();}catch(Exception e) {return Response.status(Status.OK).entity("增添用户失败,错误信息:"+e.toString()).build();}}@DELETE@Path("/{userid}/delete")public Response delete(@PathParam("userid") String userid) {userMap.remove(userid);String output = userid + " 删除成功!";return Response.status(Status.OK).entity(output).build();}}8.在src/main/resources建立一个application.properties文件server.servlet.context-path=/RestWS9.至此,工程已经搭建完毕,可以直接运行SpringBootRun的main方法启动程序10.也可以把pom.xml文件的打包类型改为<packaging>war</packaging>用外置Tomcat运行(必须要Tomcat 8.5或以上版本)二.使用Java编写客户端进行访问测试(使用Junit5进行单元测试)11.在src/test/java新建一个junittest包并新建UserTest类,然后直接执行:右键->Run As->Junit Test即可,无需手动启动SpringBootRun服务package junittest;import .URI;import javax.ws.rs.client.ClientBuilder;import javax.ws.rs.client.Entity;import javax.ws.rs.client.WebTarget;import javax.ws.rs.core.MediaType;import javax.ws.rs.core.Response;import org.junit.jupiter.api.BeforeEach;import org.junit.jupiter.api.Test;import org.junit.jupiter.api.MethodOrderer;import org.junit.jupiter.api.Order;import org.junit.jupiter.api.TestMethodOrder;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.context.annotation.Description;import springboot.jaxrs.SpringBootRun;import er;@TestMethodOrder(MethodOrderer.OrderAnnotation.class)//搭配@Order可以实现按顺序执行,但是@Test一定要使用JUnit5的注解才起作用@SpringBootTest(classes = SpringBootRun.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)//指定了程序入口SpringBootRun和使用默认端口,执行JUnit Test的时候会自动启动项目,无需手动启动项目public class UserTest {private URI uri;private User user;@BeforeEachpublic void init() throws Exception {uri = new URI("http://127.0.0.1:8080/RestWS/services/ws/users");user = new User("xiaohong","ID0001","123456");}@Test@Order(1)@Description("添加或替换用户")public void addOrUpdateTest() {System.out.println("==================================1==================== ================");WebTarget target =ClientBuilder.newClient().target(uri).path("/"+user.getIdNo()+"/addOrReplace");Response res =target.request().accept(MediaType.TEXT_PLAIN).put(Entity.entity(user, MediaType.APPLICATION_JSON));System.out.println("状态码:"+res.getStatus());if (res.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+res.getStatus());}String output = res.readEntity(String.class);System.out.println(output);System.out.println("======================================================= ===============");}@Test@Order(2)@Description("获取单个用户")public void getByIdTest() {System.out.println("==================================2==================== ================");WebTarget target =ClientBuilder.newClient().target(uri).path("/"+user.getIdNo()+"/get");Response res =target.request().accept(MediaType.APPLICATION_JSON).get();System.out.println("状态码:"+res.getStatus());if (res.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+res.getStatus());}String output = res.readEntity(String.class);System.out.println(output);System.out.println("======================================================= ===============");}@Test@Order(3)@Description("修改用户")public void updateTest() {System.out.println("==================================3==================== ================");user.setName("小红");WebTarget target =ClientBuilder.newClient().target(uri).path("/"+user.getIdNo()+"/update");Response res =target.request().accept(MediaType.TEXT_PLAIN).post(Entity.entity(user, MediaType.APPLICATION_JSON));System.out.println("状态码:"+res.getStatus());if (res.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+res.getStatus());}String output = res.readEntity(String.class);System.out.println(output);System.out.println("======================================================= ===============");}@Test@Order(4)@Description("获取全部用户")public void getAllUserTest() {System.out.println("==================================4==================== ================");WebTarget target =ClientBuilder.newClient().target(uri).path("/getAllUser");Response res =target.request().accept(MediaType.APPLICATION_JSON).get();System.out.println("状态码:"+res.getStatus());if (res.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+res.getStatus());}String output = res.readEntity(String.class);System.out.println(output);System.out.println("======================================================= ===============");}@Test@Order(5)@Description("删除用户")public void deleteTest() {System.out.println("==================================5==================== ================");WebTarget target =ClientBuilder.newClient().target(uri).path("/"+user.getIdNo()+"/delete");Response res =target.request().accept(MediaType.APPLICATION_JSON).delete();System.out.println("状态码:"+res.getStatus());if (res.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+res.getStatus());}String output = res.readEntity(String.class);System.out.println(output);System.out.println("======================================================= ===============");}}三.使用html页面访问Restful服务12.在src/main/resources里新建static文件夹,再在static文件夹新建js,pages 2个文件夹,然后js文件夹引入axios.min.js,vue.min.js。
Spring核心技术详解

Spring核⼼技术详解⼀、Sring简介Spring是⼀个分层的Java SE/EE应⽤⼀站式的轻量级开源框架。
Spring核⼼是IOC和AOP。
Spring主要优点包括:⽅便解耦,简化开发,通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进⾏控制,避免硬编码造成的程序耦合度⾼。
AOP编程的⽀持,通过Spring提供的AOP功能,⽅便进⾏⾯向切⾯编程。
声明式事务的⽀持,在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式⽅式灵活地进⾏事务的管理,提⾼开发效率和质量。
⽅便程序的测试,可以⽤⾮容器依赖的编程⽅式进⾏⼏乎所有的测试⼯作。
⽅便集成各种优秀框架,Spring提供了对各种优秀框架的直接⽀持。
⼆、Spring体系结构如下图所⽰,整个spring框架按其所属功能可以划分为五个主要模块,这五个模块⼏乎为企业应⽤提供了所需的⼀切,从持久层、业务层到表现层都拥有相应的⽀持,这就是为什么称Spring是⼀站式框架的原因。
核⼼模块(Core Container) Spring的核⼼模块实现了IoC的功能,它将类和类之间的依赖从代码中脱离出来,⽤配置的⽅式进⾏依赖关系描述。
由IoC容器负责类的创建,管理,获取等。
BeanFactory接⼝是Spring框架的核⼼接⼝,实现了容器很多核⼼的功能。
Context模块构建于核⼼模块之上,扩展了BeanFactory的功能,包括国际化,资源加载,邮件服务,任务调度等多项功能。
ApplicationContext是Context模块的核⼼接⼝。
表达式语⾔(Expression Language)是统⼀表达式语⾔(EL)的⼀个扩展,⽀持设置和获取对象属性,调⽤对象⽅法,操作数组、集合等。
使⽤它可以很⽅便的通过表达式和Spring IoC容器进⾏交互。
AOP模块Spring AOP模块提供了满⾜AOP Alliance规范的实现,还整合了AspectJ这种AOP语⾔级的框架。
contextconfiguration 用法

文章标题:深入理解contextconfiguration的用法在软件开发中,环境配置是一个至关重要的部分。
而在Spring框架中,contextconfiguration(上下文配置)则是一个非常重要的概念。
本文将带你深入了解contextconfiguration的用法,让你对这一概念有一个全面、深入的理解。
1. 什么是contextconfiguration?contextconfiguration是Spring Test框架中的注解,它为测试类提供了Spring应用程序上下文的配置选项。
通过使用contextconfiguration注解,我们可以指定一个或多个配置类来加载Spring应用程序上下文,以供测试类使用。
这样做的好处在于,我们可以在测试期间使用和验证真实的Spring容器,而不是使用模拟对象。
2. contextconfiguration的基本用法在使用contextconfiguration注解时,我们可以通过其locations属性来指定配置文件的路径,也可以通过classes属性来指定配置类。
例如:```java@ContextConfiguration(locations = {"/applicationContext.xml"}) public class MyTest {// test code}```或者```java@ContextConfiguration(classes = {AppConfig.class, DatabaseConfig.class})public class MyTest {// test code}```通过以上的简单示例,我们可以看到contextconfiguration注解的基本用法。
它让我们可以灵活地指定Spring应用程序上下文的配置方式,以适应不同的测试需求。
3. contextconfiguration的高级用法除了基本的用法之外,contextconfiguration还提供了许多高级的配置选项。
springmvc之单元测试(MockMvc)-独立测试

springmvc之单元测试(MockMvc)-独⽴测试spring mvc测试框架提供了两种⽅式,独⽴安装和集成Web环境测试(此种⽅式并不会集成真正的web环境,⽽是通过相应的Mock API进⾏模拟测试,⽆须启动服务器)1、mockMvc.perform执⾏⼀个请求;2、MockMvcRequestBuilders.get("/user/1")构造⼀个请求3、ResultActions.andExpect添加执⾏完成后的断⾔4、ResultActions.andDo添加⼀个结果处理器,表⽰要对结果做点什么事情,⽐如此处使⽤MockMvcResultHandlers.print()输出整个响应结果信息。
5、ResultActions.andReturn表⽰执⾏完成后返回相应的结果。
MockMvcBuilder是⽤来构造MockMvc的构造器,其主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder,StandaloneMockMvcBuilder继承了DefaultMockMvcBuilder。
直接使⽤静态⼯⼚MockMvcBuilders创建即可:MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下⽂获取相应的控制器并得到相应的MockMvc;MockMvcBuilders.standaloneSetup(Object... controllers):通过参数指定⼀组控制器,这样就不需要从上下⽂获取了;其中DefaultMockMvcBuilder还提供了如下API:addFilters(Filter... filters)/addFilter(Filter filter, String... urlPatterns):添加javax.servlet.Filter过滤器defaultRequest(RequestBuilder requestBuilder):默认的RequestBuilder,每次执⾏时会合并到⾃定义的RequestBuilder中,即提供公共请求数据的;alwaysExpect(ResultMatcher resultMatcher):定义全局的结果验证器,即每次执⾏请求时都进⾏验证的规则;alwaysDo(ResultHandler resultHandler):定义全局结果处理器,即每次请求时都进⾏结果处理;dispatchOptions:DispatcherServlet是否分发OPTIONS请求⽅法到控制器;StandaloneMockMvcBuilder继承了DefaultMockMvcBuilder,⼜提供了如下API:setMessageConverters(HttpMessageConverter<?>...messageConverters):设置HTTP消息转换器;setValidator(Validator validator):设置验证器;setConversionService(FormattingConversionService conversionService):设置转换服务;addInterceptors(HandlerInterceptor... interceptors)/addMappedInterceptors(String[] pathPatterns, HandlerInterceptor... interceptors):添加spring mvc拦截器;setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager):设置内容协商管理器;setAsyncRequestTimeout(long timeout):设置异步超时时间;setCustomArgumentResolvers(HandlerMethodArgumentResolver... argumentResolvers):设置⾃定义控制器⽅法参数解析器;setCustomReturnValueHandlers(HandlerMethodReturnValueHandler... handlers):设置⾃定义控制器⽅法返回值处理器;setHandlerExceptionResolvers(List<HandlerExceptionResolver>exceptionResolvers)/setHandlerExceptionResolvers(HandlerExceptionResolver... exceptionResolvers):设置异常解析器;setViewResolvers(ViewResolver...resolvers):设置视图解析器;setSingleView(View view):设置单个视图,即视图解析时总是解析到这⼀个(仅适⽤于只有⼀个视图的情况);setLocaleResolver(LocaleResolver localeResolver):设置Local解析器;setFlashMapManager(FlashMapManager flashMapManager):设置FlashMapManager,如存储重定向数据;setUseSuffixPatternMatch(boolean useSuffixPatternMatch):设置是否是后缀模式匹配,如“/user”是否匹配"/user.*",默认真即匹配;setUseTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch):设置是否⾃动后缀路径模式匹配,如“/user”是否匹配“/user/”,默认真即匹配;addPlaceHolderValue(String name, String value) :添加request mapping中的占位符替代;因为StandaloneMockMvcBuilder不会加载Spring MVC配置⽂件,因此就不会注册我们需要的⼀些组件,因此就提供了如上API⽤于注册我们需要的相应组件。
【SpringFramework】Spring入门教程(三)使用注解配置

【SpringFramework】Spring⼊门教程(三)使⽤注解配置本⽂主要介绍四个⽅⾯:(1) 注解版本IOC和DI(2) Spring纯注解(3) Spring测试(4) SpringJDBC - Spring对数据库的操作使⽤注解配置Spring⼊门说在前⾯学习基于注解的IoC配置,⼤家脑海⾥⾸先得有⼀个认知,即注解配置和xml配置要实现的功能都是⼀样的,都是要降低模块间的耦合度。
仅仅只是配置的形式不⼀样。
关于实际的开发中到底使⽤xml还是注解,每家公司有着不同的使⽤习惯。
所以这两种配置⽅式我们都需要掌握。
基于注解配置的⽅式也已经逐渐代替xml配置。
所以我们必须要掌握使⽤注解的⽅式配置Spring。
配置步骤注意:如果使⽤Eclipse需要先安装了STS插件,或者使⽤STS开发⼯具创建项⽬。
本⽂使⽤IDEA进⾏演⽰。
1.2.1. 第⼀步:拷贝必备jar包到⼯程的lib⽬录。
注意:在基于注解的配置中,我们还要多拷贝⼀个aop的jar包。
如下图:1.2.2. 第⼆步:在类的根路径下创建⼀个任意名称的xml⽂件(不能是中⽂)注意:基于注解整合时,Spring配置⽂件导⼊约束时需要多导⼊⼀个context命名空间下的约束。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context.xsd"></beans>1.2.3. 第⼆步:创建⼀个服务类创建⼀个测试的服务类,并且加⼊使⽤@Component注解,声明该类允许注⼊到Spring容器package org.cjw.service;import ponent;/*使⽤注解配置时,需要将Spring框架启动就创建对象的类表⽰为组件类表⽰组件类使⽤@Component注解*/@Componentpublic class CustomerService {public void save() {System.out.println("-保存数据-");}}1.2.4. 第四步在spring的配置⽂件加⼊扫描注解<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context.xsd"><!-- 声明扫描包及其⼦包的类,如果发现有组件注解的类,就创建对象并加⼊到容器中去 --><context:component-scan base-package="org.cjw" /></beans>1.2.5. 第五步:测试调⽤代码package org.cjw.test;import org.cjw.service.CustomerService;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class CustomerServiceTest {@Testpublic void testSave() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");CustomerService customerService = context.getBean(CustomerService.class);customerService.save();}}--测试结果,如果可以调⽤服务⽅法,测试成功。
18、springcloud如何使用spring-test进行单元测试
18、springcloud如何使⽤spring-test进⾏单元测试上篇和⼤家学习了spring cloud 如何整合reids,在测试时借⽤了web形式的restful接⼝进⾏的。
那还有没有别的⽅式可以对spring boot和spring cloud编写的代码进⾏单元测试呢?答案:肯定是有的。
这篇讲解⼀下如何使⽤ spring-boot-starter-test进⾏单元测试1、新建项⽬sc-test,对应的pom.xml⽂件如下<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>spring-cloud</groupId><artifactId>sc-test</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>sc-test</name><url></url><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.4.RELEASE</version></parent><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Finchley.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><piler.source>1.8</piler.source><piler.target>1.8</piler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>mons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId><scope>test</scope></dependency> --></dependencies></project>说明:只要使⽤spring-boot-starter-test即可,该jar已经包含spring-boot-test2、新建spring boot启动类package sc.test;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class TestApplication {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}}备注:如果没有该类,spring-test启动将报错,见下图3、新建操作redis的配置类package sc.test.config;import java.io.Serializable;import org.springframework.boot.autoconfigure.AutoConfigureAfter;import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)public class RedisCacheAutoConfiguration {@Beanpublic RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) { RedisTemplate<String, Serializable> template = new RedisTemplate<>();//键的序列化⽅式template.setKeySerializer(new StringRedisSerializer());//值的序列化⽅式template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setConnectionFactory(redisConnectionFactory);return template;}}4、新建配置⽂件application.ymlserver:port: 9005spring:application:name: sc-redisredis:host: 127.0.0.1password:port: 6379timeout: 10000 # 连接超时时间(毫秒)database: 0 # Redis默认情况下有16个分⽚,这⾥配置具体使⽤的分⽚,默认是0 lettuce:pool:max-active: 8 # 连接池最⼤连接数(使⽤负值表⽰没有限制)默认8max-wait: -1 # 连接池最⼤阻塞等待时间(使⽤负值表⽰没有限制)默认 -1 max-idle: 8 # 连接池中的最⼤空闲连接默认8min-idle: 0 # 连接池中的最⼩空闲连接默认05、新建测试类TestRedis.javapackage sc.test.unit;import java.io.Serializable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.stream.IntStream;import org.junit.Test;import org.junit.runner.RunWith;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.test.context.junit4.SpringRunner;import er;@RunWith(SpringRunner.class)@SpringBootTestpublic class TestRedis {private static final Logger log = LoggerFactory.getLogger(TestRedis.class);@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate RedisTemplate<String, Serializable> redisCacheTemplate;@Testpublic void get() {// 测试线程安全// ExecutorService executorService = Executors.newFixedThreadPool(1000);// IntStream.range(0, 1000).forEach(i ->// executorService.execute(() -> stringRedisTemplate.opsForValue().increment("kk", 1)) // );stringRedisTemplate.opsForValue().set("key", "{'name':'huangjinjin', 'age':30}");final String value = stringRedisTemplate.opsForValue().get("key");("[字符缓存结果] - [{}]", value);String key = "manage:user:1";User u = new User();u.setId(1L);u.setAge(30);u.setPosition("cto");u.setUserName("good boy");redisCacheTemplate.opsForValue().set(key, u);//从缓存获取User对象final User user = (User) redisCacheTemplate.opsForValue().get(key);("[对象缓存结果] - userName={}, age={}, position={}", //user.getUserName(), user.getAge(), user.getPosition());}}6、进⾏测试(1) reids server没有启动时,运⾏TestRedis.java(右键选择Junit Test)连接不上Reids server异常(2) reids server启动后时,运⾏TestRedis.java,出现绿条说明执⾏代码成功⽇志中打印相关数据,说明数据也存贮到redis server中7、使⽤redis-cli验证数据是否正在存档redis server中有了spring-boot-starter-test,就可以不使⽤restful接⼝对spring boot写的接⼝进⾏单元测试了。
后端开发常用的框架及其实现原理
后端开发常用的框架及其实现原理随着互联网的迅速发展,后端开发的重要性也越来越凸显。
后端开发主要负责网站、应用程序等服务的运行与实现,包括数据库的设计与管理,服务器端的业务逻辑设计与开发等。
后端开发需要使用一些框架和工具来提高效率,本文将介绍常见的后端开发框架及其实现原理。
一、Spring框架Spring框架是Java应用程序开发的一个全栈框架,它提供了一系列的解决方案,包括Web应用程序开发、AOP编程、事务管理、数据存储、消息传递、安全性等方面。
Spring框架是以IOC容器和AOP两大核心特性为主要实现原理的。
IOC容器:IOC是Inversion of Control的缩写,翻译为“控制反转”。
它的实现原理是将对象的创建、处理和销毁等过程交给了IOC 容器控制,降低了对象之间的耦合性。
Spring框架中的IOC容器是以BeanFactory的形式实现的,可以通过XML、注解或Java代码的方式进行配置。
在Spring框架中,BeanFactory是接口类,ApplicationContext是BeanFactory的子类,一般推荐使用ApplicationContext。
AOP:AOP是Aspect Oriented Programming的缩写,翻译为“面向切面编程”。
它的主要目的是将各个模块之间交叉的切面代码抽取出来,统一进行管理。
Spring框架中的AOP通过动态代理技术实现,每个切面都被包装成一个代理类,并且使用XML、注解或Java代码进行配置。
二、Django框架Django框架是基于Python语言的一个开源Web框架,它提供了一系列的组件和方法,极大地简化了Web应用程序的开发过程,包括URL 路由、模板引擎、ORM等。
Django框架的实现原理是MVT的模式。
MVT模式:MVT是Model-View-Template的缩写,翻译为“模型-视图-模板”。
它将Web应用程序分为三层,分别是模型、视图和模板。
spring事件驱动模型简介
spring事件驱动模型简介事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的⼏个关键点:1. ⾸先是⼀种对象间的⼀对多的关系;最简单的如交通信号灯,信号灯是⽬标(⼀⽅),⾏⼈注视着信号灯(多⽅);2. 当⽬标发送改变(发布),观察者(订阅者)就可以接收到改变;3. 观察者如何处理(如⾏⼈如何⾛,是快⾛/慢⾛/不⾛,⽬标不会管的),⽬标⽆需⼲涉;所以就松散耦合了它们之间的关系。
接下来先看⼀个⽤户注册的例⼦:⽤户注册成功后,需要做这么多事:1、加积分2、发确认邮件3、如果是游戏帐户,可能赠送游戏⼤礼包4、索引⽤户数据…………问题:1. UserService和其他Service耦合严重,增删功能⽐较⿇烦;2. 有些功能可能需要调⽤第三⽅系统,如增加积分/索引⽤户,速度可能⽐较慢,此时需要异步⽀持;这个如果使⽤Spring,可以轻松解决,后边再介绍;从如上例⼦可以看出,应该使⽤⼀个观察者来解耦这些Service之间的依赖关系,如图:增加了⼀个Listener来解耦UserService和其他服务,即注册成功后,只需要通知相关的监听器,不需要关系它们如何处理。
增删功能⾮常容易。
这就是⼀个典型的事件处理模型/观察者,解耦⽬标对象和它的依赖对象,⽬标只需要通知它的依赖对象,具体怎么处理,依赖对象⾃⼰决定。
⽐如是异步还是同步,延迟还是⾮延迟等。
上边其实也使⽤了DIP(依赖倒置原则),依赖于抽象,⽽不是具体。
还是就是使⽤了IoC思想,即以前主动去创建它依赖的Service,现在只是被动等待别⼈注册进来。
其他的例⼦还有如GUI中的按钮和动作的关系,按钮和动作本⾝都是⼀种抽象,每个不同的按钮的动作可能不⼀样;如“⽂件-->新建”打开新建窗⼝;点击“关闭”按钮关闭窗⼝等等。
主要⽬的是:松散耦合对象间的⼀对多的依赖关系,如按钮和动作的关系;如何实现呢?⾯向接⼝编程(即⾯向抽象编程),⽽⾮⾯向实现。
spring框架概述
spring框架概述1 spring框架概述1.1 什么是springSpring是⼀个开源框架,Spring是于2003 年兴起的⼀个轻量级的Java 开发框架,由Rod Johnson开发。
它是为了解决企业应⽤开发的复杂性⽽创建的。
框架的主要优势之⼀就是其分层架构,分层架构允许使⽤者选择使⽤哪⼀个组件,同时为J2EE 应⽤程序开发提供集成的框架dao(JdbcTemplate) service(spring控制事务) web(springmvc)Spring的核⼼是控制反转(IoC)和⾯向切⾯(AOP)。
简单来说,Spring是⼀个分层的JavaSE/EE full-stack 轻量级开源框架。
1)IoC 和DI 2)AOP⼀句话描述spring:full-stack 轻量级开源框架分层: full-stack,每⼀个层都提供解决⽅案web层:struts,spring-MVCservice层:spring 事务控制 springdao层:hibernate,mybatis , jdbcTemplate(spring提供了⼀个模板对象) --> spring-datassh:struts2+spring+hibernate(以前的了解⼀下)ssm:spring+springmvc+mybatis(现阶段常⽤)1.2 spring核⼼Spring的核⼼是控制反转(IoC)和⾯向切⾯(AOP)1.3 spring优点1.4 spring体系结构核⼼容器:beans、core、context、expressiondao service 对象的创建交给spring2 ⼊门案例:IoC【掌握】2.1 导⼊jar包4 + 1 : 4个核⼼(beans、core、context、expression) + 1个依赖(commons-loggins...jar)2.2 ⽬标类1. 提供UserService接⼝和实现类2. 获得UserService实现类的实例之前开发中,直接new⼀个对象即可。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Spring TestContext测试框架本文参考了很多网上资料及Spring reference,详细介绍了Spring TestContext测试框架常用的一些东东.若有疑问<ymkyve501@>目录直接使用Junit测试Spring程序存在的不足 (2)Spring TestContext 测试框架体系结构 (2)TestContext 核心类、支持类以及注解类 (2)TestContext (2)TestContextManager (3)TestExecutionListener (3)@TestExecutionListeners (3)@ContextConfiguration (4)@RunWith (4)SpringJUnit4ClassRunner (4)ContextCache (4)ContextLoader (5)ApplicationContextAware (5)AbstractJUnit4SpringContextTests (5)AbstractTransactionalJUnit4SpringContextTests (5)常用注解 (6)@IfProfileValue (6)@ProfileValueSourceConfiguration (6)@DirtiesContext (7)@ExpectedException (7)@Timed (7)@Repeat (8)@Rollback (8)@Transactional (8)@NotTransactional (8)@Autowired (8)@Resource (9)@Qualifier (9)@TransactionConfiguration (10)@BeforeTransaction (10)@AfterTransaction (10)总结 (10)基于注解的TestContext测试框架,它采用注解技术可以让POJO成为Spring的测试用例,可以运行在Junit3.8 Junit4.4 TestNG等测试框架之下直接使用Junit测试Spring程序存在的不足1.导致Spring容器多次初始化问题:根据JUnit 测试用例的调用流程,每执行一个测试方法都会重新创建一个测试用例实例并调用其setUp() 方法。
由于在一般情况下,我们都在setUp() 方法中初始化Spring 容器,这意味着测试用例中有多少个测试方法,Spring 容器就会被重复初始化多少次。
2.需要使用硬编码方式手工获取Bean在测试用例中,我们需要通过ApplicationContext.getBean() 的方法从Spirng 容器中获取需要测试的目标Bean,并且还要进行造型操作。
3.数据库现场容易遭受破坏测试方法可能会对数据库记录进行更改操作,破坏数据库现场。
虽然是针对开发数据库进行测试工作的,但如果数据操作的影响是持久的,将会形成积累效应并影响到测试用例的再次执行。
举个例子,假设在某个测试方法中往数据库插入一条ID 为1 的t_user 记录,第一次运行不会有问题,第二次运行时,就会因为主键冲突而导致测试用例执行失败。
所以测试用例应该既能够完成测试固件业务功能正确性的检查,又能够容易地在测试完成后恢复现场,做到踏雪无迹、雁过无痕。
4.不容易在同一事务下访问数据库以检验业务操作的正确性当测试固件操作数据库时,为了检测数据操作的正确性,需要通过一种方便途径在测试方法相同的事务环境下访问数据库,以检查测试固件数据操作的执行效果。
如果直接使用JUnit 进行测试,我们很难完成这项操作。
Spring 测试框架是专门为测试基于Spring 框架应用程序而设计的,它能够让测试用例非常方便地和Spring 框架结合起来,以上所有问题都将迎刃而解。
Spring TestContext 测试框架体系结构TestContext 核心类、支持类以及注解类TestContext 测试框架的核心由org.springframework.test.context 包中三个类组成,分别是TestContext 和TestContextManager 类以及TestExecutionListener 接口。
每次测试都会创建TestContextManager。
TestContextManager管理了一个TestContext,它负责持有当前测试的上下文。
TestContextManager还负责在测试执行过程中更新TestContext的状态并代理到TestExecutionListener,它用来监测测试实际的执行(如提供依赖注入、管理事务等等)TestContextTestContext:封装测试执行的上下文,与当前使用的测试框架无关。
TestContextManagerTestContextManager:Spring TestContext Framework的主入口点,负责管理单独的TestContext并在定义好的执行点上向所有注册的TestExecutionListener发出事件通知:测试实例的准备,先于特定的测试框架的前置方法,迟于后置方法。
TestExecutionListenerTestExecutionListener:定义了一个监听器API与TestContextManager发布的测试执行事件进行交互,而该监听器就是注册到这个TestContextManager上的。
Spring提供了TestExecutionListener的三个实现,他们都是使用默认值进行配置的(通过@TestExecutionListeners注解):DependencyInjectionTestExecutionListener、DirtiesContextTestExecutionListener及TransactionalTestExecutionListener,他们对测试实例提供了依赖注入支持,处理@DirtiesContext注解,并分别使用默认的回滚语义对测试提供事务支持。
DependencyInjectionTestExecutionListener:该监听器提供了自动注入的功能,它负责解析测试用例中@Autowried 注解并完成自动注入;DirtiesContextTestExecutionListener:一般情况下测试方法并不会对Spring 容器上下文造成破坏(改变Bean 的配置信息等),如果某个测试方法确实会破坏Spring 容器上下文,你可以显式地为该测试方法添加@DirtiesContext 注解,以便Spring TestContext 在测试该方法后刷新Spring 容器的上下文,而DirtiesContextTestExecutionListener 监听器的工作就是解析@DirtiesContext 注解;TransactionalTestExecutionListener:它负责解析@Transaction、@NotTransactional以及@Rollback 等事务注解的注解。
@Transaction 注解让测试方法工作于事务环境中,不过在测试方法返回前事务会被回滚。
你可以使用@Rollback(false) 让测试方法返回前提交事务。
而@NotTransactional 注解则让测试方法不工作于事务环境中。
此外,你还可以使用类或方法级别的@TransactionConfiguration 注解改变事务管理策略@TestExecutionListeners用来注册TestExecutionListener@TestExecutionListeners({DependencyInjectionTestExecutionListener. class, DirtiesContextTestExecutionListener.class})@ContextConfiguration用来指定加载的Spring配置文件的位置,会加载默认配置文件1. locations属性@ContextConfiguration不带locations属性,GenericXmlContextLoader会基于测试类的名字产生一个默认的位置.如果类名叫做com.example.MyTest,那么GenericXmlContextLoader就会从"classpath:/com/example/MyTest-context.xml"加载应用上下文。
@ContextConfiguration 若带有locations属性@ContextConfiguration(locations={ "spring-service.xml","spring-service1.xml" }) 会去加载指定文件2.inheritLocations属性@ContextConfiguration的inheritLocations属性 (是否继承父类的locations),默认为true@ContextConfiguration(locations={"/base-context.xml"})@ContextConfiguration(locations={"/extended-context.xml"})为true时,会将/base-context.xml, /extended-context.xml 合并加载,若有重载的bean为子类为准为false时,会屏蔽掉父类的资源位置@RunWith@RunWith 注解指定测试用例的运行器@RunWith(SpringJUnit4ClassRunner.class)SpringJUnit4ClassRunnerSpring TestContext 框架提供了扩展于org.junit.internal.runners.JUnit4ClassRunner 的SpringJUnit4ClassRunner 运行器,它负责总装Spring TestContext 测试框架并将其统一到JUnit 4.4 框架中。
它负责无缝地将TestContext 测试框架移花接木到JUnit 4.4 测试框架中,它是Spring TestContext 可以运行起来的根本所在持有TestContextManager的引用private final TestContextManager testContextManager;ContextCache缓存ApplicationContextContextLoaderInterface 加载context接口GenericXmlContextLoader为默认的ContextLoader ApplicationContextAware自动加载ApplicationContextAbstractJUnit4SpringContextTests对集成了Spring TestContext Framework与JUnit 4.4环境中的ApplicationContext测试支持的基本测试类进行了抽取。