您的位置:首页 > 编程语言 > Java开发

基于SpringBoot框架的单元测试和集成测试的区别和联系

2017-12-19 19:56 706 查看

1、单元测试和集成测试的区别:

Web集成测试:在嵌入式的Servlet容器(Tomcat,Jetty)里启动应用程序,在真正的应用服务器里进行测试。

Spring Mock MVC :能在一个接近真实的模拟Servlet容器里启动应用程序,而不用实际启动应用服务器,相当于单元测试。

2、可以采用Spring MVC进行单元测试,包括:

standaloneSetup():手工创建并配置的控制器

webAppContextSetup():使用应用程序上下文来构建MockMVC

前者更加接近单元测试,专注于单一控制器的测试,后者更加接近集成测试,让Spring加载控制器以及依赖。

3、常见的单元测试的例子:

单元测试代码

/**
* Created by wangxx-j on 2017/12/6.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@SpringBootTest(classes = {ProjectConfigApplication.class},
properties = {"EUREKA_DEFAULT_ZONE=http://192.168.xxx.xxx:10000/eureka/"})
@ActiveProfiles("unit-test")
public class ProjectConfigDictControllerTest extends ControllerTestSupport{

@Test
public void testQueryDefaultProjectConfig() throws Exception{
List<ProjectConfigDict> projectConfigDicts = get("/project-config-dict/query",List.class);
System.out.println("默认配置信息:"+projectConfigDicts);
}

}


其中,

@WebAppConfiguration


注解表示采用的上面2中webAppContextSetup(),采用应用程序上下文来进行单元测试。

@SpringBootTest(classes = {ProjectConfigApplication.class},
properties = {"EUREKA_DEFAULT_ZONE=http://192.168.xxx.xxx:10000/eureka/"})
@ActiveProfiles("unit-test")


因为我们的项目采用的是SpringCloud的框架,使用eureka服务器注册了服务,所以每个服务的配置信息都是从注册中心读取的,这里读取的是单元测试unit-test的配置。

如果你写的是一个普通的项目,那么可以将配置文件直接写到application.yml中,程序默认直接读取本地配置。

application.yml文件格式如下

spring:
redis:
host: 192.168.xxx.xxx
port: 6379
pool:
max-idle: 10
max-total: 20
max-wait: 2000
datasource:
druid:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.xxx.xxx:3306/unit_test_org_v3?characterEncoding=UTF-8
username: xxx
password: xxx
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.xxx.xxx:3306/unit_test_org_v3?characterEncoding=UTF-8
username: xxx
password: xxx


如果,你有redis服务,就需要配置redis服务器地址,等信息。

如果你有数据库访问服务,就需要配置datasource等信息。

辅助单元测试的类

ControllerTestSupport.java

public abstract class ControllerTestSupport {
protected static MockMvc mockMvc;
private static final Long TENANT_ID = 100000L;

private static final String HEADER_TENANT_ID = "x-tenant-id";
@Autowired
private WebApplicationContext context;

private void initAction(ResultActions actions, List<CheckProperty> properties)
throws Exception {
if (null == properties || properties.size() == 0) {
return;
}
for (CheckProperty property : properties) {
if (property instanceof CheckValueProperty) {
actions.andExpect(jsonPath("$." + property.getPropertyName(), equalTo(((CheckValueProperty) property).getValue())));
} else if (property instanceof CheckNullProperty) {
boolean isNull = ((CheckNullProperty) property).isNull();
if (isNull) {
actions.andExpect(jsonPath("$." + property.getPropertyName(), nullValue()));
} else {
actions.andExpect(js
4000
onPath("$." + property.getPropertyName(), notNullValue()));
}
}
}
}

protected <T> T put(String uriPath, Object data,
List<CheckProperty> properties, Class<T> tClass)
throws Exception {
ResultActions actions = getMockMvc().perform(
MockMvcRequestBuilders
.put(uriPath)
.header(HEADER_TENANT_ID, TENANT_ID)
.content(JSON.toJSONBytes(data))
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.accept(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(status().isOk());
initAction(actions, properties);
MvcResult mvcResult = actions.andReturn();
return convert(mvcResult, tClass);
}

protected <T> T get(String uriPath, Class<T> tClass)
throws Exception {
return get(uriPath, tClass, HttpStatus.OK.value());
}

protected <T> T get(String uriPath, Class<T> tClass, int status)
throws Exception {
MvcResult mvcResult = getMockMvc().perform(
MockMvcRequestBuilders
.get(uriPath)
.header(HEADER_TENANT_ID,TENANT_ID)
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.accept(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(status().is(status))
.andReturn();
return convert(mvcResult, tClass);
}

protected <T> T convert(MvcResult mvcResult, Class<T> tClass) throws Exception {
if (null == tClass) {
return null;
}
String content = mvcResult.getResponse().getContentAsString();
T actionResult = JSONObject.parseObject(content, tClass);
return actionResult;
}

private synchronized MockMvc getMockMvc() {
if (null == mockMvc) {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
return mockMvc;
}
}


其中,我们看到:

initAction函数是在post、get方法中调用的,主要是处理一些特殊的属性,比如有枚举类型的。

convert方法是为了得到返回的结果,将json转化为对应的类。

getMockMvc是模拟上下文构建Servlet容器,和第二点的webAppContextSetup对应。

CheckProperty.java:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CheckProperty {
private String propertyName;
}


CheckValueProperty .java:

@Data
@EqualsAndHashCode(callSuper = true)
public class CheckValueProperty extends CheckProperty {
private Object value;

public CheckValueProperty(String name, Object value) {
super(name);
setValue(value);
}
}


CheckNullProperty .java:

@Data
@EqualsAndHashCode(callSuper = true)
public class CheckNullProperty extends CheckProperty {
private boolean isNull;

public CheckNullProperty(String name, boolean isNull) {
super(name);
setNull(isNull);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐