- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
系列文章目录和关于我 。
最近在新公司第一次上手写代码,写了一个不是很难的业务逻辑代码,但是在我写单元测试的时候,发现自己对单元测试的理解的就是一坨,整个过程写得慢,还写得臭。造成这种局面我认为是因为:
now,我将从这两个部分来学习一下单元测试,如何写,如何写好单元测试?
在上一份工作,我基本上不咋写单元测试,觉得很麻烦,不如直接postman,swagger开冲,这种显然不容易覆盖到所有的case.
单元测试的好处:
增强信心 。
单元测试覆盖率越高,我们越对自己的代码有信心.
揭示意图 。
写单元测试的时候,我们是明确自己的代码到底是出于什么目的写的 。
安全重构 。
不只是重构,哪怕后续在原有功能上进行添加,通过执行之前存在单元测试有助于我们验证,我们没有影响到原有功能.
快速反馈 。
写单元测试的过程,我们其实有可能发现自己代码存在的缺陷,通过单元测试直白的报错,我们可以很快得到反馈,这个反馈速度是测试滴滴你所不具备的.
定位缺陷 。
单元测试并不能帮我们找出所有存在的bug(测试同事:没事,我会出手),但是我们发现bug后,可以将输入放在单元测试中进行回放,直到可以重现并定位到问题,然后使用这种情况的case来补充单元测试用例.
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-inline -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.7.7</version>
<scope>test</scope>
</dependency>
junit 。
提供了许多方便使用的注解,标注在方法上 。
Mockito 。
Mockito 是一种 Java Mock 框架,主要就是用来做 Mock 测试的,可以模拟出一个对象、模拟方法的返回值、模拟抛出异常,模拟静态方法等等,同时也会记录调用这些模拟方法的参数、调用顺序,从而可以校验出这个 Mock 对象是否有被正确的顺序调用,以及按照期望的参数被调用.
Mock 测试:比如我们的Service依赖其他的服务提供的接口方法,使用mock可以模拟出这个接口的表现(正常返回,抛出异常等到)从而让单元测试不那么依赖外部的服务.
powermock 。
可以看作是mock增强版本,提供模拟私有方法等功能,我们这里没有进行引入.
如上图,我们的MyService依赖于OtherClient,这个OtherClient可能由于网络原因会出现错误,或者其他情况抛出异常,我们的MyService需要进行处理.
打桩可以理解为 mock 对象规定它的行为,使其按照我们的要求来执行具体的操作.
//让client在query入参为1的时候,返回100为key,aaa为value的单键值对的map
Mockito.when(client.query(1)).thenReturn(new HashMap<>(Collections.singletonMap(100, "aaaa")));
Map<Integer, String> res = client.query(1);
Assert.assertEquals(1, res.size());
Assert.assertEquals(res.get(100), "aaaa");
Mockito.when(client.query(2)).thenThrow(new RuntimeException("222"));
Assert.assertThrows("222", RuntimeException.class, () -> client.query(2));
Mockito.when(client.query(Mockito.anyInt())).thenReturn(new HashMap<>());
Assert.assertEquals(0, client.query(-1).size());
有时候,我们希望入参入参符合要的时候,mock对象进行什么操作.
如下,我们要求mock对象在输入参数是 1, 2, 3 的时候返回空map 。
HashSet<Integer> integers = new HashSet<>(Arrays.asList(1, 2, 3));
Mockito.when(client.query(Mockito.argThat(new ArgumentMatcher<Integer>() {
@Override
public boolean matches(Integer argument) {
return integers.contains(argument);
}
}))).thenReturn(Collections.emptyMap());
Assert.assertEquals(0,client.query(2).size());
有时候我们希望mock对象可以根据输出的不同返回不同的结果,符合我们要求的结果.
如下,我们使用thenAnswer根据入参返回不同的结果.
Mockito.when(client.query(Mockito.anyInt())).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Integer argument = invocation.getArgument(0);
String str = argument%2==0?"偶数":"奇数";
return new HashMap<Integer,String>(Collections.singletonMap(argument,str));
}
});
Assert.assertEquals("偶数", client.query(2).get(2));
上面都是说mock对象如何去控制输出,thenCallRealMethod可以让mock对象执行真实的逻辑.
Mockito.when(client.query(-1)).thenCallRealMethod();
verify可以让我们验证当前mock对象,比如下面验证client至少执行了四次query 。
//验证 client.query最起码调用了4次
Mockito.verify(client,Mockito.atLeast(4)).query(Mockito.anyInt());
有时候静态方法也需要进行mock控制,可以使用 。
如上图,我们的MyService依赖于OtherClient,这个OtherClient可能由于网络原因会出现错误,或者其他情况抛出异常,我们的MyService需要进行处理.
上面这个例子中,OtherClient是外部提供给我们的接口,它存在一定的机率失败,在单元测试的过程我们需要mock它的行为,而不是真的去调用外部接口.
这里我们得明确 MyService是我们需要测试的,那就别mock它,OtherClient是外部依赖,需要进行mock控制其行为.
最后此篇关于单元测试与Mockito的文章就讲到这里了,如果你想了解更多关于单元测试与Mockito的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我一直面临一个奇怪的问题。基本上,当我正常运行 Mockito 测试时,即“作为 Junit 测试运行”时,它给了我以下错误。有人可以帮助我请问我的错误是什么? 收到的错误: java.lan
我正在使用 Mockito 以及 mockito-inline用于模拟静态方法。我正在尝试申请 doNothing或类似的行为,到静态 void 方法。以下解决方法有效,但我认为应该有一种更方便的方法
我正在尝试验证我正在测试的类是否调用了正确的依赖类的方法。所以我试图匹配方法参数,但我并不真正关心这个测试中的实际值,因为我不想让我的测试变得脆弱。 但是,我在设置它时遇到了麻烦,因为 Mockito
我正在使用 Mockito 编写单元测试,并且在模拟注入(inject)的类时遇到问题。问题是两个注入(inject)的类是相同的类型,仅通过它们的 @Qualifier 注释进行区分。如果我尝试简单
在我的断言中的以下简单练习中,我期望 1,但得到 0。为什么我会看到这种行为? public class MockitoTest { POJO mockedPojo; @Before
我正在创建一个通用模拟客户端来测试 HTTP 交互。为此,我希望能够以相同的方法进行多次响应。使用普通模拟,这不是问题: when(mock.execute(any(), any(), any()))
我需要全局模拟类方法。 我的意思是,我不能创建模拟对象和 stub 方法。我的 api 不将此对象作为参数,所以我不能在函数调用中传递它,但是这个类的对象是在这些函数中创建并在那里使用的。这就是为什么
我正在尝试使用 Mockito 2.18.3 框架模拟我们公司内部库中提供的 final 类,不幸的是我们无权更改库中的代码。但每当我运行时,我都会收到以下错误: java.lang.NoClassD
研究了mockito测试框架,学习了powermock,突然发现一个叫powermockito的框架,看不懂了。 谁能告诉我这三个测试工具的区别? 最佳答案 Mockito 是市场标准模拟框架,味道非
我想跳过检查验证调用中的参数之一。因此对于: def allowMockitoVerify=Mockito.verify(msg,atLeastOnce()).handle(1st param,,3r
为了模拟在被测方法内部构造的本地对象上的局部变量/方法调用,我们目前使用的是 PowerMockito 库。 我们正在尝试评估是否可以使用 mockito-inline(版本 3.7.7)来做同样的事
我在想, 如果在 @Before 方法中我正在初始化模拟对象,我不应该在 @After 中取消对它的引用吗?或者那会是多余的吗?为什么? 最佳答案 不需要,JUnit 会为每个测试方法创建一个新的测试
我想使用 Mockito 验证字符串参数是否满足两个条件: verify(mockClass).doSomething(Matchers.startsWith("prefix")); verify(m
如果我像这样创建一个模拟 when(servicesTestEnv.mockUserProfileAndPortfolioTransactionRepository.get(servicesTestE
使用 Mockito 我遇到了以下问题: Mockito.when(restOperationMock.exchange( Mockito.anyString(), M
我想知道描述中的事情是否可行以及如何去做。 我知道你可以调用原始方法然后像这样做答案: when(presenter, "myMethod").doAnswer() 但我想对它们进行不同的排序,首先执
我试图弄清楚org.mockito.AdditionalMatchers是如何工作的,但我失败了。为什么这个测试失败了? import static org.hamcrest.CoreMatchers
有人知道使用 Mockito 为 ATG 编写单元测试用例吗?我在凝视时遇到了以下讨论 - Automated unit tests for ATG development和 Using PowerM
我想知道描述中的事情是否可行以及如何去做。 我知道你可以调用原始方法然后像这样做答案: when(presenter, "myMethod").doAnswer() 但我想对它们进行不同的排序,首先执
我有以下接口(interface)CatalogVersionService,它公开了一些服务。我还有一个单元测试,它通过使用 Mockito 来模拟这个接口(interface),如下所示: Cat
我是一名优秀的程序员,十分优秀!