工作记录------单元测试
之前的工作中从来没有写过单元测试,新入职公司要求写单元测试,
个人觉得,作为程序员单元测试还是必须会写的
于此记录一下首次编写单元测试的过程。
首先引入单元测试相关的依赖
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
其次创建test目录
在src目录下,创建与main同级的目录。
其中test/java目录下编写测试类
test/resources目录下放置测试所需要的配置文件。
test/java与main/java目录层级结构保持一致。
区别在于测试类以Test结尾。
测试类编写
@RunWith(MockitoJUnitRunner.class)
public class ATest {
private static final Logger LOGGER = LoggerFactory.getLogger(A.class);
@InjectMocks
private A a;
@Mock
private B b;
@Mock
private C c;
@Mock
private D d;
@Mock
private E e;
@Mock
private F f;
private H h = new H();
@Test
public void testGetType() {
Enum type = a.getType();
boolean equals = type.equals(Enum.SAVE);
Mockito.when(d.d(Mockito.anyString(), Mockito.any(), Mockito.any())).thenReturn("123456789");
AppLogUtil.info(LOGGER, "Enum.SAVE result:{}", equals);
}
@Before
public void init() {
MockitoAnnotations.initMocks(this);
f.setB("aaa");
}
首先在文件头声明这是一个测试类:@RunWith(MockitoJUnitRunner.class)
这是一个A类的测试类,所以文件名为ATest。
@InjectMocks:
作用是:注入mock
意味着在测试过程中进入A类时,A类中所涉及的引用都是有值的,不为null,指的是A类中的(B-F)。
@Mock:
就是模拟这个引用的依赖,用于Test类
@Before:
执行@Test方法前,先执行的步骤,一般用于参数构建,以及mock注入:MockitoAnnotations.initMocks(this);这句话与@InjectMocks相结合使用,表明注入模拟A类。
@Test:
指的是拥有这个注解的方法就是测试方法,通过这个方法对A类中的具体方法进行测试,而方法名一般为“test方法名”。需要传递参数的话,就需要先构建对应的参数。
而由于A类中涉及到了很多依赖的调用,此时我们也需要mock返回参数,使得流程能正常的跑下去。
由此能够看出,单元测试只针对当前一个方法的逻辑,不会延伸到引用调用的方法。
当遇到其他引用的方法调用时,也需要mock,比如执行到D类的d方法,就需要Mockito.when(d.d(Mockito.anyString(), Mockito.any(), Mockito.any())).thenReturn(“123456789”);根据这个语句能够看出,d方法需要三个参数,该方法需要几个参数,就传入几个参数。thenReturn代表模拟的返回值。
问题:如果在A类中,调用B引用的select方法,两次,一次返回null,一次返回有值,应该怎么操作?
答案:
Mockito.when(B.select(Mockito.anyString())).thenReturn(null).thenReturn(dto);
通过两次thenReturn方法,第一次则会返回第一次thenReturn的结果,第二次会返回第二次thenReturn的结果
此时dto需要自行new
230831日记录
首先明确init()方法
这个方法里添加写的应该是当前测试类,需要公共注入的配置,单个方法用到的注入配置,就应该放到测试方法中,单独声明
@Before
public void init() {}
遇到问题,如何链式调用mock
遇到调用redis模版的方法。需要mock,但mock一直不通过,启动测试方法时会报异常
NullpointerException
回到测试类中。发现自己引入时,是这样的写法。
Mockito.when(redisTemplate.opsForValue().increment(Mockito.anyString(), Mockito.any())).thenReturn(1l);
回到原代码,原始代码如下,此处的key是个固定值
redisTemplate.opsForValue().increment(key, -1l);
发现这样mock是无效的,缺少对应的引用,因为mock引用时,也只引用了stringRedisTemplate,对于stringRedisTemplate.opsForValue()方法缺少返回值。
@Mock
private StringRedisTemplate redisTemplate;
后经过指点遇到链式调用时,需要都mock文章来源:https://www.toymoban.com/news/detail-626386.html
@Mock
private StringRedisTemplate redisTemplate;
@Mock
ValueOperations<String, String> valueOperations;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
Mockito.when(redisTemplate.opsForValue()).thenReturn(valueOperations);
//此时的key = "123",需要和真实代码中使用相同的key
Mockito.when(redisTemplate.increment("123",-1)).thenReturn(1L);
}
注意点
当我们使用Mockito.when,来表明执行到该方法时,调用mock的方法,和返回mock的结果。
此时传入的参数,应该和业务代码中保持一致,而不是简单的使用Mockito.anyString()、Mockito.any()随意应付的写传入任意参数。文章来源地址https://www.toymoban.com/news/detail-626386.html
Mockito.when(mybkService.queryDetail("1111","1111",null,"1111","1111","1111",1,1)).thenReturn(StudVo);
到了这里,关于工作记录------单元测试(持续更新)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!