一、介绍
1.1 介绍
1. 多人协作下的测试有什么不同(Mock)
2. 如何编写单元测试(依赖外部、不依赖外部两种情况)
3. 如何排查慢方法、测方法耗时
二、测试与调试
2.1 多人协作下的测试有什么不同
1. 依赖别人开发的接口
2. 联调?等待?反复沟通?
3. Mock技术
Mockito
古巴最著名的鸡尾酒Mojito
使用最广泛的模拟库之一
Mockito的能力有多强?
引入依赖
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.9.0</version>
<scope>test</scope>
</dependency>
编写测试类。创建Mock对象,Mock对象的返回。Spy来部分模拟某对象。@Mock @Spy注解。
package com.imooc.cloud.mall.practice.user.service.impl;
import java.util.HashMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.test.context.SpringBootTest;
/**
* 描述: TODO
*/
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class UserServiceImplTest {
// @Mock //对等1
// HashMap myHashMap;
@Test
public void myFirstMock() {
HashMap mockHashMap = Mockito.mock(HashMap.class); //对等1
Mockito.when(mockHashMap.size()).thenReturn(5);
System.out.println(mockHashMap.size());
mockHashMap.put(new Object(), new Object());
System.out.println(mockHashMap.size());
}
@Spy //对等2
HashMap<String, String> hashMap = new HashMap<>();
@Test
public void myFirstSpy() {
//HashMap<String, String> hashMap = new HashMap<>(); //对等2
//spy定制的意思。对一部分想定制的方法进行定制,不想定制的方法用原来的能力。
HashMap<String, String> spy = Mockito.spy(hashMap);
spy.put("1","2");
System.out.println(spy.size());
spy.put("2","3");
Mockito.when(spy.size()).thenReturn(10);
System.out.println(spy.size());
}
}
2.2 如何编写单元测试
平常的单元测试
package com.imooc.cloud.mall.practice.user.service.impl;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.imooc.cloud.mall.practice.common.exception.ImoocMallException;
import com.imooc.cloud.mall.practice.common.exception.ImoocMallExceptionEnum;
import com.imooc.cloud.mall.practice.user.model.dao.UserMapper;
import com.imooc.cloud.mall.practice.user.model.pojo.User;
import java.time.Duration;
import java.time.Instant;
import java.util.LinkedList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit4.statements.SpringRepeat;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringRunner.class) //需要Spring注入的能力
@SpringBootTest
public class UserTest {
@Autowired
UserMapper userMapper;
@Test
@Transactional //测试时,对数据库的修改会在测试结束后回滚
@Rollback(true)//事务自动回滚,默认是true。更加明显的事务回滚标记。
//普通的不使用mock的单元测试
public void testUpdateInformation() {
//1 currentTimeMillis
long start = System.currentTimeMillis();
User user = new User();
user.setId(9);
user.setPersonalizedSignature("新签名");
long finish = System.currentTimeMillis();
long timeElapsed = finish - start;
System.out.println("currentTimeMillis:" + timeElapsed);
//2 nanoTime
//更新个性签名
long start2 = System.nanoTime();
int updateCount = userMapper.updateByPrimaryKeySelective(user);
long finish2 = System.nanoTime();
timeElapsed = finish2 - start2;
System.out.println("nanoTime:" + timeElapsed / 1000000);
if (updateCount > 1) {
throw new ImoocMallException(ImoocMallExceptionEnum.UPDATE_FAILED);
}
//3 Instant
Instant start3 = Instant.now();
User newUser = userMapper.selectByPrimaryKey(user.getId());
Instant finish3 = Instant.now();
long timeElapsed3 = Duration.between(start3, finish3).toMillis();
System.out.println(timeElapsed3);
Assert.assertEquals(newUser.getPersonalizedSignature(), user.getPersonalizedSignature());
}
}
带远程调用的单元测试
package com.imooc.cloud.mall.practice.cartorder.service.impl;
import com.imooc.cloud.mall.practice.cartorder.feign.ProductFeignClient;
import com.imooc.cloud.mall.practice.cartorder.model.pojo.Product;
import com.imooc.cloud.mall.practice.cartorder.model.vo.CartVO;
import com.imooc.cloud.mall.practice.common.common.Constant.SaleStatus;
import com.imooc.cloud.mall.practice.common.exception.ImoocMallException;
import com.imooc.cloud.mall.practice.common.exception.ImoocMallExceptionEnum;
import junit.framework.TestCase;
import org.apache.commons.lang.time.StopWatch;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 描述: TODO
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderServiceImplTest{
@Mock
ProductFeignClient productFeignClient;
@Test
public void validSaleStatusAndStockTest() throws InterruptedException {
StopWatch watch = new StopWatch(); //StopWatch代码
watch.start(); //StopWatch代码
CartVO cartVO = new CartVO();
cartVO.setProductId(27);
cartVO.setQuantity(1);
Product fakeProduct = new Product();
fakeProduct.setStatus(1);
fakeProduct.setStock(4);
Thread.sleep(1000);
watch.split(); //StopWatch代码
System.out.println("split time:" + watch.getSplitTime()); //StopWatch代码
Thread.sleep(1500);
Mockito.when(productFeignClient.detailForFeign(27)).thenReturn(fakeProduct);
Product product = productFeignClient.detailForFeign(cartVO.getProductId());
long time = watch.getTime(); //StopWatch代码
System.out.println("time elapsed:" + time); //StopWatch代码
watch.suspend(); //StopWatch代码 暂停
//判断商品是否存在,商品是否上架
if (product == null || product.getStatus().equals(SaleStatus.NOT_SALE)) {
throw new ImoocMallException(ImoocMallExceptionEnum.NOT_SALE);
}
Thread.sleep(3000);
//判断商品库存
if (cartVO.getQuantity() > product.getStock()) {
throw new ImoocMallException(ImoocMallExceptionEnum.NOT_ENOUGH);
}
watch.resume(); //StopWatch代码 恢复
Thread.sleep(500);
System.out.println("time elapsed:" + watch.getTime()); //StopWatch代码
Assert.assertNotNull(product);
Assert.assertEquals(1, (int)product.getStatus());
Assert.assertTrue(product.getStock() > cartVO.getQuantity());
}
}
2.3 如何排查慢方法,测方法耗时
currentTimeMillis()(有缺陷,用的系统时间为标准,代码可能修改系统时间,导致测量结果不准确)
nanoTime()(纳秒,1000000纳秒=1毫秒)
Instant类
StopWatch(计时,split,暂停恢复{跳过不计时某部分代码} )
代码在上面