【高效编码】深入TestNG体验了一把,真爽

举报
码农飞哥 发表于 2021/05/28 22:50:36 2021/05/28
【摘要】 您好,我是码农飞哥,感谢您阅读本文!如果此文对您有所帮助,请毫不犹豫的一键三连吧。小伙伴们,有啥想看的,想问的,欢迎积极留言。上一篇文章对TestNG做了一个简单的体验。我们了解了其是什么,有什么用,重点介绍了其各种注解。但是这些都不够深入,不够爽。实际项目中怎么运用呢?没有说,实在不过瘾。 这篇文章就让我们来深入体验一下TestNG。看看到底好不好用,用的爽不爽。 ...

您好,我是码农飞哥,感谢您阅读本文!如果此文对您有所帮助,请毫不犹豫的一键三连吧。小伙伴们,有啥想看的,想问的,欢迎积极留言上一篇文章对TestNG做了一个简单的体验。我们了解了其是什么,有什么用,重点介绍了其各种注解。但是这些都不够深入,不够爽。实际项目中怎么运用呢?没有说,实在不过瘾。
这篇文章就让我们来深入体验一下TestNG。看看到底好不好用,用的爽不爽。
在这里插入图片描述

搭建项目,添加待测试类

首先,还是搭建一个SpringBoot框架的项目,怎么搭建项目,在此就不赘述了,想了解的朋友可以参考这篇文章Spring Boot 学习01-----搭建一个简单的spring-boot-demo
项目搭建好之后,这里添加了几个待测试的方法。代码如下:

@RestController
public class TestNgController { @Autowired private TestNgService testNgService; @PostMapping("/v1/user/add") public String addUser(String userName, String password) { boolean result = testNgService.saveUser(userName, password); return result ? "{\"code\":\"200\",\"msg\":\"用户保存成功\"}" : "{\"code\":\"500\",\"msg\":\"用户保存失败\"}"; } @GetMapping("/v1/user/get") public String getUser(String userName) { boolean result = testNgService.getUserByName(userName); return "{\"code\":\"200\",\"msg\":\"获取用户成功\"}"; } @RequestMapping("/v1/user/update") public String updateUser(@RequestBody User user) { boolean result = testNgService.updateUser(user); return result ? "{\"code\":\"200\",\"msg\":\"用户修改成功\"}" : "{\"code\":\"500\",\"msg\":\"用户修改失败\"}"; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

这里分别有:

  1. 用户保存接口/v1/user/add,请求类型是application/form-data
  2. 获取用户接口/v1/user/get,请求类型是application/form-data
  3. 用户更新接口/v1/user/update ,这个的请求类型是application/json
    三个接口,下面分别对这三个接口进行单元测试。

引入依赖

  1. 针对接口的测试需要引入的依赖有,spring-boot-starter-test主要是引入Spring-Test 依赖,因为需要使用 @SpringBootTest,testng依赖就不用多说了,今日份主角。
  <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.10</version> <scope>test</scope> </dependency>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

编写单元测试基类

  1. 设置单元测试基类
@SpringBootTest
public class TestNgControllerTest  extends AbstractTestNGSpringContextTests { private MockMvc mockMvc; @Autowired private WebApplicationContext webApplicationContext; @BeforeClass public void setUp(){ //必须用webAppContextSetup方法设置web环境 this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build(); } //通用返回结果的封装 public String getResultCode(MockHttpServletRequestBuilder requestBuilder) { try { MvcResult mvcResult = mockMvc.perform(requestBuilder) .andDo(print()) .andExpect(status().isOk()) .andReturn(); String result = mvcResult.getResponse().getContentAsString(); JSONObject jsonObject = JSON.parseObject(result); return jsonObject.getString("code"); } catch (Exception e) { e.printStackTrace(); } return null; }
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

是不是感觉跟前面Junit 整合SpringBoot的单元测试基类有点像呢?对的没错,长的确实有点像,因为其中MvcResult对象和MockMvc对象因为来自spring-test。所以,getResultCode方法是一模一样的,都是针对返回类型是application/json格式的返回做了处理。
需要特别注意的是与Junit的不同点:

  1. 继承AbstractTestNGSpringContextTests 类。
    因为这个类实现了ApplicationContextAware接口(Spring会检查实现该接口的类,并通过setApplicationContext方法注入ApplicationContext对象)。可以获取到这个ApplicationContext系统上下文对象,而WebApplicationContext对象是ApplicationContext对象的子类。
  2. 通过 @BeforeClass 注解修饰的方法来初始化MockMvc对象。
    最主要的原因是AbstractTestNGSpringContextTests类中通过springTestContextPrepareTestInstance来准备初始化的对象
	@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextBeforeTestClass")
	protected void springTestContextPrepareTestInstance() throws Exception {		this.testContextManager.prepareTestInstance(this);
	}

  
 
  • 1
  • 2
  • 3

所以在@BeforeClass运行之前执行的方法都不能获取对象。即使用@BeforeSuite或者是@BeforeTest注解修饰的话,则初始化方法运行时ApplicationContext还没有被注入进来。如果用@BeforeMethod修饰的话,则每个测试方法执行之前都会执行一次。
补充说明:@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextBeforeTestClass") dependsOnMethods属性表示该方法依赖于springTestContextBeforeTestClass方法,就是说springTestContextBeforeTestClass必须要先于springTestContextPrepareTestInstance执行,同时alwaysRun = true 表示依赖者和被依赖者之间必须不存在成功失败的因果关系,只需要被依赖的方法执行即可。

编写单元测试方法

基类编写好之后,就相当于是打好了基础,下面只要搬砖了。首先编写保存用户的测试方法

 @Test public void testAddUser() { System.out.println("线程="+Thread.currentThread().getName()+"执行testAddUser"); //保存成功 { MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/v1/user/add") .param("userName", "张三") .param("password", "123"); String resultCode = getResultCode(requestBuilder); Assert.assertEquals("200", resultCode); } //保存失败的情况 { MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/v1/user/add") .param("userName", "李四") .param("password", "123"); String resultCode = getResultCode(requestBuilder); Assert.assertEquals("500", resultCode); } }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

这里有保存成功和保存失败两种情况。代码的编写跟使用Junit时是一模一样的,还是实例化MockHttpServletRequestBuilder对象,传入接口地址和入参。在此不在赘述了。执行结果是:
在这里插入图片描述
直接运行单元测试类,三个测试方法的运行线程都是主线程,不是说testNG可以进行并发测试么?没看到呀,不要着急,这就来进行并发测试。

并发测试

建立一个TestNG的XML文件,命名为TestNgControllerTestSuite.xml。

<?xml version="1.0" encoding="UTF-8" ?>
<suite name="Suite" parallel="methods" thread-count="4"> <test name="Test"> <classes> <class name="com.jay.testng.TestNgControllerTest"/> </classes> </test>
</suite>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

其中与并发测试相关的配置是:

<suite name="Suite" parallel="methods" thread-count="4">

  
 
  • 1

在当前测试规划的执行过程中,为每个方法(不管是不是通过@Test修饰的方法)进行并发执行,最多4个线程,下面就是运行结果
在这里插入图片描述
当然还有其他的配置,比如:

  1. 针对测试方法
<suite name="Suite" parallel="tests" thread-count="4">

  
 
  • 1

在当前测试规划的执行过程中,为每个测试方法(只有通过@Test修饰的方法)进行并发执行,最多4个线程。
2. 针对测试类

<suite name="Suite" parallel="classes" thread-count="4">

  
 
  • 1

在当前测试规划的执行过程中,为每个测试类的执行使用单独的线程(该测试类中的测试方法共享一个线程),最多并发4个线程。
在这里插入图片描述

总结

本文详细介绍了TestNG与SpringBoot的整合,还介绍了并发测试。

文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。

原文链接:feige.blog.csdn.net/article/details/116637835

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。