Mockito+Testng+Assertj的使用实例
写测试用例时,如果只关注输入、输出或是否被调用,建议使用Mock框架,能使用Mock的框架有EasyMock、Mockito、PowerMock、JMock等;
Mock框架在处理”黑洞”接口,有特别的效果,
下面来分享下Mockito框架的使用:
假如说我现在项目有三层,
- 第一层是入口层,我把它叫做”access”;
- 第二层是业务处理层,我把它叫做”business”;
- 第三层是数据处理层,我把她叫做”resource”;
单元测试
是指对软件中的最小可测试单元进行检查和验证。
现在我分情况来说明一下怎么利用Mockito框架去进行Mock测试;
单独测试access层,跳过business和resource层
只需要把business层Mock掉就可以了,因为resource层是有business层去调用,所以不必理会,下面上例子:
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.Date;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.*;
public class ServiceAccessTest {
private int customerId = 2;
private int invalidCustomerId =0;
@Mock
private DemoBusiness demoBusiness; //需要Mock的business层
@Mock
private StreamObserver<DemoResponse> demoSO;
@InjectMocks
DemoServiceAccess demoServiceAccess;//需要测试的access层
//跑测试前要进行的初始化
@BeforeMethod
public void setup() {
demoServiceAccess = new DemoServiceAccess();
MockitoAnnotations.initMocks(this);
}
//测试跑完后需要做的事情
@AfterMethod
public void after() {
reset(demoBusiness, demoSO);
reset(demoBusiness, helpDemoSO);
reset(demoBusiness, getDemoLogSO);
}
@Test
public void DemoTest_Success() {
DemoBusinessPojo demoPojo = new DemoBusinessPojo();
demoPojo.setContinueDays(5);
demoPojo.setIncreaseScore(5);
demoPojo.setLastTime(new Date().getTime());
demoPojo.setTotalTimes(11);
when(demoBusiness.summit(customerId)).thenReturn(demoPojo);
ArgumentCaptor<DemoResponse> ac = ArgumentCaptor.forClass(DemoResponse.class);
demoServiceAccess.summit(DemoRequest.newBuilder().setCustomerId(customerId).build(), demoSO);
verify(demoSO).onNext(ac.capture());
reset(demoBusiness);
}
@Test(expectedExceptions = InvalidArgumentException.class)
public void DemoFailTest() {
demoServiceAccess.summit(DemoRequest.newBuilder().setCustomerId(invalidCustomerId).build(), demoSO);
}
@SuppressWarnings("unchecked")
@Test(expectedExceptions = StatusRuntimeException.class)
public void DemoFailTest1() {
when(demoBusiness.summit(customerId)).thenThrow(ResourceUnavailableException.class);
demoServiceAccess.summit(DemoRequest.newBuilder().setCustomerId(customerId).build(), demoSO);
}
@SuppressWarnings("unchecked")
@Test(expectedExceptions = Exception.class)
public void DemoFailTest2() {
when(demoBusiness.summit(customerId)).thenThrow(Exception.class);
demoServiceAccess.summit(DemoRequest.newBuilder().setCustomerId(customerId).build(), demoSO);
}
单独测试business层,跳过resource层
因为是单元测试,所以之前的access层我们也不必去理会了,从而只Mock层就OK了,下面上例子:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
import org.testng.annotations.Test;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import static org.assertj.core.api.Assertions.assertThat;
@ProfileTest
@ProfileDevelop //环境为dev
@ContextConfiguration(classes = {DemoBusiness.class})//加载类,如果有多个类,可以用","隔开,往后添加
@TestPropertySource(value = "classpath:application.properties")//加载配置文件
public class DemoBusinessTest extends AbstractTransactionalTestNGSpringContextTests {
@Autowired
private DemoBusiness demoBusiness;//需要测试的business层
@Autowired
private DemoResources demoResources;//需要Mock层
@Test
public void demoNormal() {
long helpCustomerId = 111;
long customerId = 100;
DemoBusinessPojo demoPojo = new DemoBusinessPojo();
demoPojo.setContinueDays(5);
demoPojo.setIncreaseScore(5);
demoPojo.setLastTime(new Date().getTime());
demoPojo.setTotalTimes(11);
//如果传过去的对象或者是参数,而在方法后面又进行重新new了一个新的对象或者参数,那么我们应该传进去的是任何的对象或者参数,
比如说,customerId传进去,但是真正到达demoBusiness.summit()里面,customerId的值动态变化,那么我们就应该
//when(demoResources.summit(any(customerId))).thenReturn(demoPojo);//Mock层
when(demoResources.summit(customerId)).thenReturn(demoPojo);//Mock层
DemoBusinessPojo demoBusinessPojo = demoBusiness.summit(customerId,
101, helpCustomerId);//测试层
assertThat(demoBusinessPojo.getIncreaseScore()).isGreaterThanOrEqualTo(1);
assertThat(demoBusinessPojo.getContinueDays()).isGreaterThanOrEqualTo(1);
assertThat(demoBusinessPojo.getLastTime()).isGreaterThan(1);
assertThat(demoBusinessPojo.getTotalTimes()).isGreaterThanOrEqualTo(1);
}
}
单独测试resource层,跳过直接访问数据库
由于到这层是需要直接访问数据库的,所以我们需要直接Mock数据库了,下面上例子:
有待完善……
集成测试
在单元测试的基础上,将所有模块按照设计要求(如根据结构图)组装成为子系统或系统,进行集成测试。
有待完善……