IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> Java白盒测试 -> 正文阅读

[开发测试]Java白盒测试

Java白盒测试

spring单元测试

环境正常单元测试

spring单元测试公共源码类

step1:工程依赖配置
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.25.RELEASE</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.6.0</version>
</dependency>
step2:@ContextConfiguration

位置:spring-test.jar / org.springframework.test.context

作用:加载配置文件用来做测试(加载applicationContext.xml)

属性:

@AliasFor("locations")
String[] value() default {};

@AliasFor("value")
String[] locations() default {};

Class<?>[] classes() default {};

String name() default "";

例子:

@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
step3:@RunWith

位置:junit.jar / org.junit.runner

作用:@RunWith是运行器,通过value设定的类来进行单元测试(运行测试类中的测试方法)

属性:

Class<? extends Runner> value()

例子:

@RunWith(value = SpringJUnit4ClassRunner.class)
step4:SpringJUnit4ClassRunner类

位置:spring-test.jar / org.springframework.test.context.junit4

作用:@RunWith是运行器,通过value设定的SpringJUnit4ClassRunner来进行单元测试

相关类:

JUnit4ClassRunner类,BlockJUnit4ClassRunner类,只能运行非spring项目的测试类
SpringJUnit4ClassRunner类是对spring项目的测试类进行单元测试的
总结
@ContextConfiguration是初始化环境,@RunWith是运行器基于刚初始化完成的环境让SpringJUnit4ClassRunner对测试类的@Test方法进行测试
spring项目做单元测试为什么不用testng,是因为testng做单元测试的类是抽象类,我们用不了

在这里插入图片描述

Controller层单元测试

单测准备
MockMvc类

位置:spring-test.jar / org.springframework.test.web.servlet

作用:支持spring MVC测试,相关的类有MockMvcRequestBuilders、MockMvcResultMatchers、MockMvcBuilders

源码:

//构造方法
MockMvc(TestDispatcherServlet servlet, Filter[] filters, ServletContext servletContext)
//普通方法
void setDefaultRequest(RequestBuilder requestBuilder)
void setGlobalResultMatchers(List<ResultMatcher> resultMatchers)
void setGlobalResultHandlers(List<ResultHandler> resultHandlers)
public ResultActions perform(RequestBuilder requestBuilder)    
MockMvcBuilders类

作用:MockMvc生成器

源码:

//类方法
public static DefaultMockMvcBuilder webAppContextSetup(WebApplicationContext context)
public static StandaloneMockMvcBuilder standaloneSetup(Object... controllers)    
例子
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@RunWith(value = SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class UserControllerLoginTest {
    @Autowired
    private WebApplicationContext context;
    private MockMvc mockMvc;
    @Before
    public void before() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }
}
单测开发
MockMvcRequestBuilders类

作用:RequestBuilder接口对象生成器

源码:

//类方法
public static MockHttpServletRequestBuilder get(URI uri)
public static MockHttpServletRequestBuilder post(URI uri)
public static MockHttpServletRequestBuilder put(URI uri)
public static MockHttpServletRequestBuilder patch(URI uri)
public static MockHttpServletRequestBuilder delete(URI uri)
public static MockHttpServletRequestBuilder options(URI uri)
public static MockHttpServletRequestBuilder head(URI uri) 
public static MockHttpServletRequestBuilder request(String httpMethod, URI uri)    
MockHttpServletRequestBuilder类

作用:此类下的方法都与发送请求有关

源码:

//类方法
public MockHttpServletRequestBuilder secure(boolean secure)
public MockHttpServletRequestBuilder characterEncoding(String encoding)
public MockHttpServletRequestBuilder content(String content)
public MockHttpServletRequestBuilder contentType(String contentType)
public MockHttpServletRequestBuilder header(String name, Object... values)
public MockHttpServletRequestBuilder param(String name, String... values)
public MockHttpServletRequestBuilder params(MultiValueMap<String, String> params)
public MockHttpServletRequestBuilder cookie(Cookie... cookies)    
ResultActions接口

作用:获取结果

源码:

//抽象方法
ResultActions andExpect(ResultMatcher matcher)	//添加执行完成后的断言
ResultActions andDo(ResultHandler handler)		//添加一个结果处理器  
MvcResult andReturn()							//返回相应的结果    
andReturn()方法结合Junit的Assert类也可以做断言但是相对繁琐,所以我们选择andExpect(ResultMatcher matcher)和andDo(ResultHandler handler)方法结合使用
MockMvcResultMatchers类

作用:基于ResultMatcher的结果操作的静态工厂方法

源码:

//类方法
public static StatusResultMatchers status()
public static HeaderResultMatchers header() 
public static ContentResultMatchers content() 
public static JsonPathResultMatchers jsonPath(String expression, Object... args)
public static CookieResultMatchers cookie()     
MockMvcResultHandlers类

作用:基于ResultHandler的结果操作的静态工厂方法

源码:

//类方法
public static ResultHandler log()
public static ResultHandler print()    
MvcResult接口

作用:提供对已执行请求结果的访问

源码:

//抽象方法
MockHttpServletRequest getRequest()   
MockHttpServletResponse getResponse() 
例子
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@RunWith(value = SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class UserControllerLoginTest {
    @Autowired
    private WebApplicationContext context;
    private MockMvc mockMvc;  
    /*接口请求基本数据*/
    private static final String REQ_URL = "/user/login.html";
    private static final String CONTENT_TYPE = "application/json;charset=UTF-8"; 
    /*测试数据相关*/
    private static final String SUCCESS_BODY = "{\"name\":\"zhangsan\",\"pwd\":\"123456\"}";   
    /*结果断言相关*/
    private static final String JSONPATH_CODE = "$.code";
    private static final Integer JSONPATH_CODE_SUCCESS_VALUE = 200;
    private static final String JSONPATH_MSG = "$.msg";
    private static final String JSONPATH_MSG_SUCCESS_VALUE = "登录成功";
    private static final String JSESSIONID = "JSESSIONID";
    
    @Before
    public void before() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }
    
   	/**
     * @Title: testLoginSuccess   
     * @Description: 测试成功登录      
     * @return: void      
     * @throws Exception
     */
    @Test
    public void testLoginSuccess() throws Exception {
        //请求数据
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sign = SignUtil.getSign(timestamp);
        //发送请求及结果断言
        success(request(timestamp, sign, SUCCESS_BODY));
    }
    
    /**
     * @Title: request   
     * @Description: 单测请求
     * @param: timestamp
     * @param: sign
     * @param: body     
     * @return: ResultActions      
     * @throws Exception
     */
    public ResultActions request(String timestamp, String sign, String body) throws Exception {
        //发送请求和得到结果
        ResultActions rs = mockMvc.perform(post(REQ_URL)
                .contentType(CONTENT_TYPE)
                .header("timestamp", timestamp)
                .header("sign", sign)
                .content(body));
        return rs;
     }
    
    /**
     * @Title: success   
     * @Description: 成功断言
     * @param: rs      
     * @return: void      
     * @throws Exception
     */    
    public void success(ResultActions rs) throws Exception {
        rs.andDo(print());
        rs.andExpect(status().isOk());
        rs.andExpect(jsonPath(JSONPATH_CODE).value(JSONPATH_CODE_SUCCESS_VALUE));
        rs.andExpect(jsonPath(JSONPATH_MSG).value(JSONPATH_MSG_SUCCESS_VALUE));
        rs.andExpect(cookie().exists(JSESSIONID));
    }    
}
单测报告
jacoco报告

认识:jacoco(java code Coverage)是一个java开源的覆盖率工具,并可与maven,eclipse,sonar,Jenkins等结合使用

作用:mvn test执行单元测试时,用jacoco插件生成单元测试结果和覆盖率

配置:pom.xml

<!-- jacoco -->
<properties>
    <jacoco.version>0.8.7</jacoco.version>
    <!-- 解决乱码问题 -->
    <argLine>-Dfile.encoding=utf-8</argLine>
</properties>

<build>
    <finalName>spring</finalName>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.version}</version>
            <executions>
                <!-- 生成jacoco.exec代理 -->
                <execution>
                    <id>default-prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
                <!-- 生成单元测试jacoco报告 -->
                <execution>
                    <id>default-report</id>
                    <phase>test</phase>
                    <goals>
                        <goal>report</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${basedir}/target/coverage-reports</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

解读
在这里插入图片描述

类覆盖率:被测class类文件是否被覆盖
方法覆盖率:被测的方法是否被覆盖
分支覆盖率:被测程序的if和switch语句的分支是否被覆盖(绿色全覆盖,红色无覆盖,黄色部分覆盖)
行覆盖率:被测的每行代码是否被覆盖
instruction覆盖率:字节码有关,分支越多,按行统计覆盖率和按instruction统计覆盖率数据有差异;反之无分支或分支少两者数据相等或接近
单测总结
A.准备测试环境
B.MockMvc创建
C.MockMvc.perform执行请求
D.ResultActions.andExpect添加执行完成后断言
E.ResultActions.andDo添加结果处理器 
F.优化代码
G.单元测试报告

Service层单元测试

场景一

单测–controller–service–dao

此场景不用做service层单测,因当前单测代码向controller层代码发请求,会覆盖service和dao层代码
场景二

当前阶段代码只有service–dao

需对service层代码做单测
步骤:
A.准备linux测试环境
B.公共源码类开发(启动spring项目环境)
C.@Autowired导入service层对象
D.@Test代码开发
E.单元测试报告
例子
@ContextConfiguration(locations= {"classpath:applicationContext.xml"})
@RunWith(value=SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class UserServiceTest {
	/*初始化*/
	private User user = new User();
	
	/*测试数据*/
	private static final int DELETE_USER_ID = 2;
	private static final int DML_DB_SUCCESS_RESULT = 1;

	@Autowired
	private UserService userService;
	
	/**
	 * @Title: testDeleteUserById   
	 * @Description: 测试服务层deleteUserById方法
	 * @param:       
	 * @return: void      
	 * @throws
	 */
	@Test
	public void testDeleteUserById() {
		user.setId(DELETE_USER_ID);
		//删除master主库用户id,删除成功则返回值是1
		Assert.assertEquals(userService.deleteUserById(user), DML_DB_SUCCESS_RESULT);
		//查询slave从库用户id
		Assert.assertEquals(ObjectUtils.isEmpty(userService.getUser(user.getId())),true);	
	}
}    

环境隔离单元测试

spring单元测试公共源码类

step1:工程依赖配置
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.25.RELEASE</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.6.0</version>
</dependency>

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.10.19</version>
    <scope>test</scope>
</dependency>
step2:@ContextConfiguration

位置:spring-test.jar / org.springframework.test.context

作用:加载配置文件用来做测试

属性:

@AliasFor("locations")
String[] value() default {};

@AliasFor("value")
String[] locations() default {};

Class<?>[] classes() default {};

String name() default "";

例子:

@ContextConfiguration(classes=MockServletContext.class)
step3:@RunWith

位置:junit.jar / org.junit.runner

作用:@RunWith是运行器,通过value设定的类来进行单元测试

属性:

Class<? extends Runner> value()

例子:

@RunWith(value = SpringJUnit4ClassRunner.class)
step4:SpringJUnit4ClassRunner类

位置:spring-test.jar / org.springframework.test.context.junit4

作用:@RunWith是运行器,通过value设定的SpringJUnit4ClassRunner来进行单元测试

Controller层单元测试

单测准备
MockMvc类

位置:spring-test.jar / org.springframework.test.web.servlet

作用:支持spring MVC测试,相关的类有MockMvcRequestBuilders、MockMvcResultMatchers、MockMvcBuilders

源码:

//构造方法
MockMvc(TestDispatcherServlet servlet, Filter[] filters, ServletContext servletContext)
//普通方法
void setDefaultRequest(RequestBuilder requestBuilder)
void setGlobalResultMatchers(List<ResultMatcher> resultMatchers)
void setGlobalResultHandlers(List<ResultHandler> resultHandlers)
public ResultActions perform(RequestBuilder requestBuilder)    
MockMvcBuilders类

作用:MockMvc生成器

源码:

//类方法
public static DefaultMockMvcBuilder webAppContextSetup(WebApplicationContext context)
public static StandaloneMockMvcBuilder standaloneSetup(Object... controllers)    
例子
@ContextConfiguration(classes=MockServletContext.class)
@RunWith(value=SpringJUnit4ClassRunner.class)
public class UserControllerMockitoLoginTest {
	
	private MockMvc mockMvc;
    
	@InjectMocks
	private UserController userController; 
    
	@Mock
	private UserService userService;
	
	@Mock
	private SignService signService;
	
	@Mock
	private SessionService sessionService;    
    
	@Before
	public void before() {
		MockitoAnnotations.initMocks(this);
		mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
	}
}
单测开发
MockMvcRequestBuilders类

作用:RequestBuilder接口对象生成器

源码:

//类方法
public static MockHttpServletRequestBuilder get(URI uri)
public static MockHttpServletRequestBuilder post(URI uri)
public static MockHttpServletRequestBuilder put(URI uri)
public static MockHttpServletRequestBuilder patch(URI uri)
public static MockHttpServletRequestBuilder delete(URI uri)
public static MockHttpServletRequestBuilder options(URI uri)
public static MockHttpServletRequestBuilder head(URI uri) 
public static MockHttpServletRequestBuilder request(String httpMethod, URI uri)    
MockHttpServletRequestBuilder类

作用:此类下的方法都与发送请求有关

源码:

//类方法
public MockHttpServletRequestBuilder secure(boolean secure)
public MockHttpServletRequestBuilder characterEncoding(String encoding)
public MockHttpServletRequestBuilder content(String content)
public MockHttpServletRequestBuilder contentType(String contentType)
public MockHttpServletRequestBuilder header(String name, Object... values)
public MockHttpServletRequestBuilder param(String name, String... values)
public MockHttpServletRequestBuilder params(MultiValueMap<String, String> params)
public MockHttpServletRequestBuilder cookie(Cookie... cookies)    
ResultActions接口

作用:获取结果

源码:

//抽象方法
ResultActions andExpect(ResultMatcher matcher)	//添加执行完成后的断言
ResultActions andDo(ResultHandler handler)		//添加一个结果处理器  
MvcResult andReturn()							//返回相应的结果    
andReturn()方法结合Junit的Assert类也可以做断言但是相对繁琐,所以我们选择andExpect(ResultMatcher matcher)和andDo(ResultHandler handler)方法结合使用
MockMvcResultMatchers类

作用:基于ResultMatcher的结果操作的静态工厂方法

源码:

//类方法
public static StatusResultMatchers status()
public static HeaderResultMatchers header() 
public static ContentResultMatchers content() 
public static JsonPathResultMatchers jsonPath(String expression, Object... args)
public static CookieResultMatchers cookie()     
MockMvcResultHandlers类

作用:基于ResultHandler的结果操作的静态工厂方法

源码:

//类方法
public static ResultHandler log()
public static ResultHandler print()    
MvcResult接口

作用:提供对已执行请求结果的访问

源码:

//抽象方法
MockHttpServletRequest getRequest()   
MockHttpServletResponse getResponse() 
Mockito相关类

位置: mockito-all.jar / org. mockito

@Mock注解类

作用:模拟1个Mock对象

源码:

String name() default ""
Class<?>[] extraInterfaces() default {}
boolean serializable() default false

@InjectMocks注解类

作用:创建某类的实例对象,@Mock出的对象会被注入到@InjectMocks对象中

MockitoAnnotations类

作用:对mockito注解初始化

源码:

public static void initMocks(Object testClass)

Mockito类

作用:Mockito库支持mock的创建及验证,打桩

源码:

public class Mockito extends Matchers    
public static <T> OngoingStubbing<T> when(T methodCall)
public static <T> T verify(T mock)
public static Stubber doAnswer(Answer answer)
public static Stubber doNothing()
public static Stubber doReturn(Object toBeReturned)
public static InOrder inOrder(Object... mocks)
public static Object[] ignoreStubs(Object... mocks)
public static VerificationMode times(int wantedNumberOfInvocations)
public static VerificationMode never()
public static VerificationMode atLeastOnce()
public static VerificationMode atLeast(int minNumberOfInvocations)
public static VerificationMode atMost(int maxNumberOfInvocations)
public static VerificationMode calls( int wantedNumberOfInvocations )
public static VerificationMode only()
public static VerificationWithTimeout timeout(long millis)
public static VerificationAfterDelay after(int millis)
public static MockSettings withSettings()    
public static boolean anyBoolean()
public static byte anyByte()
public static char anyChar()
public static int anyInt()
public static long anyLong()
public static float anyFloat()
public static double anyDouble()
public static short anyShort()
public static <T> T anyObject()
public static <T> T anyVararg()
public static <T> T any(Class<T> clazz)
public static <T> T any()
public static String anyString()
public static List anyList()
public static Set anySet()
public static Map anyMap()
public static Collection anyCollection()
public static boolean eq(boolean value)
public static byte eq(byte value)
public static char eq(char value)
public static double eq(double value)
public static float eq(float value)
public static int eq(int value)
public static long eq(long value)
public static short eq(short value)
public static <T> T eq(T value)
public static <T> T refEq(T value, String... excludeFields)
public static <T> T same(T value)
public static Object isNull()
public static Object notNull()
public static Object isNotNull()
public static String contains(String substring)
public static String matches(String regex)
public static String endsWith(String suffix)
public static <T> T argThat(Matcher<T> matcher)
public static char charThat(Matcher<Character> matcher)
public static boolean booleanThat(Matcher<Boolean> matcher)
public static byte byteThat(Matcher<Byte> matcher)
public static short shortThat(Matcher<Short> matcher)
public static int intThat(Matcher<Integer> matcher)
public static long longThat(Matcher<Long> matcher)
public static float floatThat(Matcher<Float> matcher)
public static double doubleThat(Matcher<Double> matcher)    
例子
@ContextConfiguration(classes=MockServletContext.class)
@RunWith(value=SpringJUnit4ClassRunner.class)
public class UserControllerMockitoLoginTest {
	
	private MockMvc mockMvc;
    /*接口请求基本数据*/
    private static final String REQ_URL = "/user/login";
    private static final String CONTENT_TYPE = "application/json;charset=UTF-8"; 
    /*测试数据相关*/
    private static final String SUCCESS_BODY = "{\"name\":\"zhangsan\",\"pwd\":\"123456\"}";   
    /*结果断言相关*/
    private static final String JSONPATH_CODE = "$.code";
    private static final Integer JSONPATH_CODE_SUCCESS_VALUE = 200;
    private static final String JSONPATH_MSG = "$.msg";
    private static final String JSONPATH_MSG_SUCCESS_VALUE = "登录成功";       
	/*mock服务相关*/
	private static final boolean  SIGN_HANDLER_SUCCESS_VALUE= true;	
	private static final long USERSERVICE_CONT_ROW_SUCCESS_VALUE= 1;	
	private static final String SESSIONSERVICE_ADDSESSION_SUCCESS_VALUE= "OK";
		
    @InjectMocks
	private UserController userController;     
	@Mock
	private UserService userService;	
	@Mock
	private SignService signService;	
	@Mock
	private SessionService sessionService;    
    
	@Before
	public void before() {
		MockitoAnnotations.initMocks(this);
		mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
	}   
	/**
	 * @Title: testLoginSuccess   
	 * @Description: 测试模拟环境-正确登录     
	 * @return: void      
	 * @throws Exception 
	 */
	@Test
	public void testLoginSuccess() throws Exception {
		//先定义模拟服务返回结果
		mockServiceRs(SIGN_HANDLER_SUCCESS_VALUE,USERSERVICE_CONT_ROW_SUCCESS_VALUE,SESSIONSERVICE_ADDSESSION_SUCCESS_VALUE);	
		//请求数据
		String timeStamp = String.valueOf(System.currentTimeMillis());
		String sign = SignUtil.getSign(timeStamp);		
		//发送请求及结果断言
		success(request(timeStamp,sign,SUCCESS_BODY));
	}    
	/**
	 * @Title: mockServiceRs   
	 * @Description: 模拟服务结果
	 * @param: handlerRs
	 * @param: countRow
	 * @param: addSessionRs      
	 * @return: void      
	 * @throws
	 */
	public void mockServiceRs(boolean handlerRs,Long countRow,String addSessionRs) {
		when(signService.handler(any())).thenReturn(handlerRs);
		when(userService.CountRowByNamePwd(any())).thenReturn(countRow);
		when(sessionService.addSession(anyString(), any())).thenReturn(addSessionRs);
	}
    /**
     * @Title: request   
     * @Description: 单测请求
     * @param: timestamp
     * @param: sign
     * @param: body     
     * @return: ResultActions      
     * @throws Exception
     */
    public ResultActions request(String timestamp, String sign, String body) throws Exception {
        //发送请求和得到结果
        ResultActions rs = mockMvc.perform(post(REQ_URL)
                .contentType(CONTENT_TYPE)
                .header("timestamp", timestamp)
                .header("sign", sign)
                .content(body));
        return rs;
     }    
    /**
     * @Title: success   
     * @Description: 成功断言
     * @param: rs      
     * @return: void      
     * @throws Exception
     */    
    public void success(ResultActions rs) throws Exception {
        rs.andDo(print());
        rs.andExpect(status().isOk());
        rs.andExpect(jsonPath(JSONPATH_CODE).value(JSONPATH_CODE_SUCCESS_VALUE));
        rs.andExpect(jsonPath(JSONPATH_MSG).value(JSONPATH_MSG_SUCCESS_VALUE));
    }            
}
总结
1、模拟环境的controller的单测,测试完毕后;一定要等service,dao开发完后,再继续做单测因模拟环境测试深度是有限的(只是测了controller层的代码)
2、需要注意的就是contentType格式转换问题,因为是环境隔离测试所以不会加载MVC的配置文件,所以我们需要修改UserController中的接口地址(将.html去掉),并且需要配置pom.xml文件依赖
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.9</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.9</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.9</version>
</dependency>
单测总结
A.公共源码类的开发
B.@InjectMocks模拟controller层对象
C.@Mock模拟service层对象
D.@Before初始化让mock生效
E.@Test开发单测用例(Mockito, Mockmvc)
F.代码优化
G.单元测试报告

Service层单元测试

单测开发

service–dao X mysql

解决问题思路
1.等mysql搭建完成,测试顺序mockmvc-controller--service--dao
2.对dao打桩, service调用dao即是人工干预的结果,测试顺序service--dao
例子
@ContextConfiguration(classes=MockServletContext.class)
@RunWith(value=SpringJUnit4ClassRunner.class)
public class UserServiceMockitTest {	
	/*初始化*/
	private User user = new User();	
	/*测试数据*/
	private static final int DELETE_USER_ID = 2;
	private static final int DML_DB_SUCCESS_RESULT = 1;

	@InjectMocks
	private UserServiceImpl userServiceImpl;	
	@Mock
	private UserMapper userMapper;
	
	@Before
	public void before() {
		MockitoAnnotations.initMocks(this);
	}	
	/**
	 * @Title: testDeleteUserById   
	 * @Description: 测试服务层deleteUserByid方法
	 * @param:       
	 * @return: void      
	 * @throws
	 */
	@Test
	public void testDeleteUserById(){
		//模拟结果
		user.setId(DELETE_USER_ID);
		when(userMapper.deleteById(user)).thenReturn(1);
		//删除master主库用户id,删除成功则返回值是1
		Assert.assertEquals(userServiceImpl.deleteUserById(user), DML_DB_SUCCESS_RESULT);
	}
}    
单测总结
需对service层代码做单测,当前阶段代码只有service--dao
步骤:
A.准备linux测试环境
B.公共源码类开发(启动spring项目环境)
C.@InjectMocks模拟接口实现类对象
D.@Mock模拟mapper层对象
E.@Before初始化让mock生效
F.@Test开发单测用例(Mockito)
G.测试报告

普通类单元测试

测试前提

pom. xml配置junit,testng,mockito-all,jacoco

单测方式

junit单测

场景1:代码类已开发完的单测
例子
public class RequestUtilTest {
	@Test
	public void testSendGet() throws Exception {
		String url = "https://ip/xxx/getinfo.html";
		String param = "pid=1";
		String rs = RequestUtil.sendGet(url, param);
		
		Assert.assertEquals("200", JSONPath.read(rs, "$.respCode"));
		Assert.assertEquals("thinkpad", JSONPath.read(rs, "$.respMsg"));
		Assert.assertEquals(8000, JSONPath.read(rs, "$.respPrice"));
	}	
	@Test
	public void testSendPost() throws Exception {
		String url = "http://ip/xxx/loginCheck";
		String param = "id=123456&passwd=123456";
		String rs = RequestUtil.sendPost(url, param);
		
		Assert.assertEquals("1", JSONPath.read(rs, "$.stateCode"));
		Assert.assertEquals("管理员登录成功", JSONPath.read(rs, "$.msg"));
	}
}
场景2:被测代码类调用其他类或第三方接口
例子

类调用类-特定场景难模拟数据单测

@RunWith(value=MockitoJUnitRunner.class)
public class AlarmTest {	
	/*
	 * 适应范围: 当前数据难提供的情况下,可用mockito
	 */	
	@Mock
	AirTemperature airTemperature;
	
	@InjectMocks
	Alarm alarm;
	/**
	 * @Title: testAlarmCase1   
	 * @Description: 测试气温<9  防寒
	 * @param:       
	 * @return: void      
	 * @throws
	 */
	@Test
	public void testAlarmCase1() {
		//模拟气温及结果断言
		when(airTemperature.getDegrees()).thenReturn(7);
		Assert.assertEquals("防寒", alarm.info());
	}	
	/**
	 * @Title: testAlarmCase2   
	 * @Description: 测试气温>=30 && <=50  防暑
	 * @param:       
	 * @return: void      
	 * @throws
	 */
	@Test
	public void testAlarmCase2() {
		//模拟气温及结果断言
		when(airTemperature.getDegrees()).thenReturn(35);
		Assert.assertEquals("防暑", alarm.info());
	}
	/**
	 * @Title: testAlarmCase3   
	 * @Description: 测试气温正常
	 * @param:       
	 * @return: void      
	 * @throws
	 */
	@Test
	public void testAlarmCase3() {
		//模拟气温及结果断言
		when(airTemperature.getDegrees()).thenReturn(15);
		Assert.assertEquals("正常", alarm.info());
	}
}

类调用第三方接口单测

@RunWith(PowerMockRunner.class)
@PrepareForTest({RequestUtil.class})
@PowerMockIgnore({"javax.net.ssl.*"})
public class OrderPayTest {	
	/*
	  适用范围: 代码依赖第三方的结果,且结果不受自己代码控制,故需模拟
	  1.模拟类-普通方法-mockito-测试类MockitoJUnitRunner.class
	    <dependency>
	  		<groupId>org.mockito</groupId>
			<artifactId>mockito-all</artifactId>
			<version>1.10.19</version>
			<scope>test</scope>
	    </dependency>
	  2.模拟类-类方法-PowerMockito-测试类PowerMockRunner.class和@PrepareForTest结合
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-core</artifactId>
			<version>1.10.19</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-api-mockito</artifactId>
			<version>1.6.5</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-module-junit4</artifactId>
			<version>1.6.5</version>
			<scope>test</scope>
		</dependency>	  
	 */	
	@InjectMocks
	private OrderPay orderPay;
	
	@Before
	public void before() {
		mockStatic(RequestUtil.class);
	}	
	/**
	 * @Title: testStatusSuccess   
	 * @Description: 支付成功测试
	 * @param:      
	 * @return: void      
	 * @throws Exception 
	 */
	@Test
	public void testStatusSuccess() throws Exception {
		//模拟结果
		when(RequestUtil.sendPost(anyString(), anyString()))
			.thenReturn("{\"msg\":\"Success\",\"state\":\"200\"}");		
		//断言结果
		Assert.assertEquals(true, orderPay.status(1, 30));
	}	
	/**
	 * @Title: testStatusFail   
	 * @Description:支付失败测试
	 * @param:    
	 * @return: void      
	 * @throws Exception   
	 */
	@Test
	public void testStatusFail() throws Exception {
		//模拟结果
		when(RequestUtil.sendPost(anyString(), anyString()))
			.thenReturn("{\"msg\":\"Fail\",\"state\":\"400\"}");		
		//断言结果
		Assert.assertEquals(false, orderPay.status(2, 30));
	}
}
场景3:模拟类集数据
例子
@RunWith(value=MockitoJUnitRunner.class)
public class ClassSetTest {
	/*
	 * 适用范围: 程序代码中因需要用到类集,但在单测是单测需要,模拟类集数据
	 */
	@Mock
	private List list;
	
	@Test
	public void testList() {
		//模拟结果
		when(list.get(anyInt())).thenReturn(1,2,3,4,5);
		when(list.isEmpty()).thenReturn(false);
	}
}

testng单测

场景同junit单测

总结单元测试

1.环境正常单测与环境隔离单测,普通类单测,在企业都用的多
2.单元测试属于白盒测试范畴,集成测试属于灰盒测试范畴,系统测试属于黑盒测试范畴,据金字塔原理测试介入早收益大
3.单元测试分为两部分:人工静态检查法与动态执行跟踪法,原则上开发完代码就要做单元测试,并要覆盖代码各种逻辑分支

在这里插入图片描述

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:30:46  更:2022-04-15 00:31:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:25:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码