Junit单元测试入门与整理

本文介绍了单元测试的重要性,详细讲解了JUnit的基本概念、注解、断言和测试方法,包括controller、service、dao层的单元测试实践。还提到了MockMvc在controller层测试的应用,以及如何对私有方法进行单元测试。文章最后分享了单元测试的注意事项和常见问题。
摘要由CSDN通过智能技术生成


单元测试整理-分享

PS:未完待续,持续更新中。。。

先简单说一下为什么要写测试用例
1. 可以避免测试点的遗漏,为了更好的进行测试,可以提高测试效率
2. 可以自动测试,可以在项目打包前进行测试校验
3. 可以及时发现因为修改代码导致新的问题的出现,并及时解决

1. 单元测试介绍:

单元测试是编写的一小段代码,用于检验目标代码的一个很小的、很明确的功能模块是否正确。为了证明这段代码的行为和我们期望的是否一致。目前的单元测试框架有JUnit、Mockito、Unitils,其中Junit是一个基于xUnit的测试框架,是目前进行单元测试的主要工具。

单元测试推荐的一本书是《JUnit实战(第2版)》。
这里写图片描述


2. idea环境相关介绍:

一个java项目应该有三个路径,Sources, Test和Resources三个部分,Sources是你的开发代码,Test是你的测试代码,Resources是你的资源文件或配置文件。
这里写图片描述

在class类名字处打开IntelliJ的quickLips,就可以看到如下的画面:
这里写图片描述

然后我们选择Create Test, 接下来会出现
这里写图片描述

idea就会生成一个这样的文件
这里写图片描述

单元测试的运行界面为
这里写图片描述
绿条表示程序正常的运行且通过了,如果为红条则表示程序中存在bug不可以正常的运行。其中console也可以显示你的所有输出。当然你也可以在非测试方法的地方右击选行运行整个测试类。


3. 单元测试基本概念:

1. JUnit基本注解介绍:

//在所有测试方法前执行一次,一般在其中写上整体初始化的代码
@BeforeClass

//在所有测试方法后执行一次,一般在其中写上销毁和释放资源的代码
@AfterClass

//在每个测试方法前执行,一般用来初始化方法(比如我们在测试别的方法时,类中与其他测试方法共享的值已经被改变,为了保证测试结果的有效性,我们会在@Before注解的方法中重置数据)
@Before

//在每个测试方法后执行,在方法执行完成后要做的事情
@After

// 测试方法执行超过1000毫秒后算超时,测试将失败
@Test(timeout = 1000)

// 测试方法期望得到的异常类,如果方法执行没有抛出指定的异常,则测试失败
@Test(expected = Exception.class)

// 执行测试时将忽略掉此方法,如果用于修饰类,则忽略整个类
@Ignore(“not ready yet”)
@Test
@RunWith

2. Junit4断言
实现数组比较断言

String[] users = new String[]{"tom", "sharp", "tony"};
Assert.assertArrayEquals(new String[]{"tom", "sharp", "tony"}, users);

3. 异常测试

//预期抛出空指针异常
@Test(expected=NullPointerException.class)
public void method() {
    assertNotNull(user.getUserName());
}

4. 超时测试

@Test(timeout = 10)//10ms
public void method() {

}

4. controller层单元测试:

环境配置:

@RunWith(SpringJUnit4ClassRunner.class) //指定测试启动器
@SpringApplicationConfiguration(classes = Application.class)//指定SpringBoot工程的Application启动类
@WebAppConfiguration //Web项目中,Junit需要模拟ServletContext,由该注解提供
@ActiveProfiles("test")
public class V2MerchantControllerTest {}

备注:如果配置不正确会导致运行失败。

对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等,这样会导致测试无法进行,为了可以对Controller进行测试,可以通过引入MockMVC进行解决。

MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。

MockMvc的初始化工作

private MockMvc mockMvc;

@Autowired
private WebApplicationContext webApplicationContext;

@Before
public void setUp() throws Exception {
    this.mockMvc = webAppContextSetup(webApplicationContext).build();
}

获取商户列表的一个测试用例:

@Test
public void getMerchantList() throws Exception {
    //mockMvc.perform(get("/v2/merchants/list"));//执行一个RequestBuilder请求
    mockMvc.perform( //执行一个RequestBuilder请求
            get("/v2/merchants/") //请求的URL, 请求的方法是get
                    .contentType(requestcontentType) //数据的格式
                    .param("userid", "2") //添加参数
                    .param("token", "1") //登录凭证
                    .param("type", "2") //1、查自己, 2、查全部
                    .param("page", "1") //默认从1开始
                    .param("limit", "20") //每页条目数, 默认20条

    )
            .andExpect(status().isOk()) //返回的状态是200
            .andDo(print())//打印出请求和相应的内容
            .andReturn().getResponse().getContentAsString(); //将相应的数据转换为字符串

}

5. service层单元测试

同controller一样的配置
示例代码:

//com.nuanyou.bdpal.service.UserService

@Test
public void findCountryCodeByUserId() throws Exception {
    System.out.println("输出结果为:");
    System.out.println(userService.findCountryCodeByUserId(14L));
    System.out.println("输出结束");
}

6. dao层单元测试

DAO层的大部分工作都是对数据库中相应的表进行CRUD操作。

示例代码:

//com.nuanyou.bdpal.dao.bd.EntityBdCertificateGroupDao

@Test
public void findByCountryIdAndUserId() throws Exception {
    System.out.println("输出的结果为:");
    System.out.println(dao.findByCountryIdAndUserId(1L, 14L));
}

注意事项:
JUnit非常智能的,他将你的测试程序执行完成之后,会回滚所有的操作,做到了测试代码不影响项目程序的要求,也就解释了为什么你测试程序运行后去查看数据库并没有变化,因为所有的操作都被回滚了。你可以通过看测试的状态条是否为绿色来判断程序的正确性,或者加入几条输入语句来confirm一下。


7. 单元测试三十六计

实际进行单元测试时,具体的情形分为很多种,实际操作比理论更加丰富。总体单元测试分为mock形式和调用真实的依赖两种,mock形式单元测试将另起一篇博客,本文主要介绍调用真实依赖时一些特殊情形的处理。

1. mock形式进行单元测试

模拟mock方式进行单元测试

2. 调用真实依赖进行单元测试

  • 对private私有方法的单元测试

对私有方法单元测试的场景比较少,目前并没有测试框架进行太好的支持,本文主要采用反射的方式进行单元测试,适用于比较简单的私有方法,对复杂的私有方法进行单元测试将是一场噩梦。具体的代码示例如下:

//实例化
Constructor<SharpDemo> constructor = SharpDemo.class.getDeclaredConstructor();
constructor.setAccessible(true);
SharpDemo sharp = constructor.newInstance();

//私有方法
Method method = sharp.getClass().getDeclaredMethod("privateMethodName", 参数1.class, 参数2.class...);
method.setAccessible(true);

//执行方法
ResultBean result = (ResultBean) method.invoke(sharp, "12345678", "abcd"...);

8. 注意事项:

JUnit注意事项
1. 测试方法上必须使用@Test进行修饰。
2. 测试方法必须使用public void进行修饰,不能带任何的参数。
3. 新建一个源代码目录来存放我们的测试代码。
4. 测试类的包应该和被测试类保持一致。
5. 测试单元中的每个方法必须可以独立测试,测试方法不能有任何的依赖。

可能遇到的问题:
1. 配置环境不正确导致运行失败
2. 测试方法应该为public

测试失败的两种情况
1. Failure一般由单元测试使用的断言方法判断失败所引起的,这表示测试点发现了问题,就是说程序输出的结果和我们预期的不一样。
2. Error是由代码异常引起的,它可以产生于测试代码本身的错误,也可以是被测试代码中的一个隐藏的bug。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值