Junit开发流程代码编写及规范详解

后台-系统设置-扩展变量-手机广告位-内容正文顶部

Junit开发指南

基类

  com.enation.app.javashop.framework.test.BaseTest

  此类加入了基础的注解:

  @RunWith(SpringRunner.class)

  @AutoConfigureMockMvc

  @SpringBootTest()

  @ComponentScan("com.enation.app.javashop")

  @Transactional

  @Rollback()

  publicabstractclassBaseTest{

  }

  基类加入了事务和自动回滚的注解,那么在单元测试中相应的操作最终会被回滚,而不影响下次测试

bootstrap.yml

  需要在src/main/test/resources中定义一个bootstrap.yml,他和main/resources中的只有一项profile不一样:

  spring:

  application:

  name:admin-api

  cloud:

  config:

  uri:http://localhost:8888

  label:master

  profile:test

  server:

  port:8082

shardingspheredruid的配置

  spring:

  shardingsphere:

  props:

  sql:

  show:true

  sharding:

  default-data-source-name:ds0

  datasource:

  names:ds0

  ds0:

  type:com.alibaba.druid.pool.DruidDataSource

  driver-class-name:com.mysql.jdbc.Driver

  url:jdbc:mysql://192.168.2.115:3306/default_database?useUnicode=true&characterEncoding=utf8&autoReconnect=true

  username:root

  password:123456

tocken权限

  在BaseTest中,定义了seller1,seller2,buyer1,buyer2四个tocken值,不需要在自己的单元测试中重复定义:

示例

  @Test

  publicvoidtestAdd(){

  Mapbrand=newHashMap();

  brand.put("name","nametest");

  brand.put("logo","logotest");

  //执行插入的操作

  daoSupport.insert("es_brand",brand);

  //在此事务中,插入的数据可见

  Stringdblogo=daoSupport.queryForString("selectlogofromes_brandwherename=?","nametest");

  //断言中也证明事务可见

  Assert.assertEquals(dblogo,"logotest");

  //测试结束后,会回滚测试中对数据库的操作

  }

多数据源事务

  我们系统因分库存在多个数据源,那么默认的事务管理是对商品库的事务管理,如果你的单元测试需要事务回滚,需要在自己的测试类上声明自己的事务管理,比如系统相关的单元测试如果要回滚:

  @Transactional(value="systemTransactionManager",rollbackFor=Exception.class)

  publicclassSettingManagerTestextendsBaseTest{

  ...

事务的周期

  值得注意的是,每个单元测试(即每个@Test)都是一个事务周期

  publicclassMyTestextendsBaseTest{

  @Test

  publicvoidtestA(){}

  @Test

  publicvoidtestB(){}

  }

  如上所示,testA中对数据的操作,在testB中是不可见的,如果有要重复利用的操作,可以在testB中调用testA:

  publicclassMyTestextendsBaseTest{

  @Test

  publicvoidtestA(){}

  @Test

  publicvoidtestB(){testA();}

  }

  当然根据你的业务场景需要,可以在自己的单元测试上注解@Rollback(false),来禁用回滚:

  @Rollback(false)

  publicclassMyTestextendsBaseTest{

  ...

  }

测试数据的准备和清除

  如果测试场景需要,可以通过@Before、@After注解来构造、清除测试所需数据:

  @Before

  publicvoidinsertTestData(){

  }

  @After

  publicvoidcleanTestData(){

  }

对象比较断言

  为了方便restfulapi的单元测试,在BaseTest中内置了一个对象比较ResultMatcher,使用方法如下:

  @Test

  publicvoidtestAdd()throwsException{

  //构建一个预期的对象

  Brandbrand=newBrand();

  brand.setName("name1");

  brand.setLog("logo1");

  //在断言中直接使用objectEquals

  mockMvc.perform(post("/goods/brands").param(...)

  .andExpect(objectEquals(brand));

  }

说明

  •   objectEquals比较的是controller中的返回值是否和预期的一样
  •   实际上是将response的body(json)转为对象,再和预期的对象进行比较
  •   这就要求要比较的对象必须实现了equals方法和toString方法

参数的批量校验

  在BaseTest中提供了一个构建多参数map的方法toMultiValueMaps,使用示例:

  @Test

  publicvoidtestAddParams()throwsException{

  //定义参数名

  String[]names=newString[]{"name","logo","message"};

  //定义几组要测试的参数情况和提示信息断言message

  String[]values1=newString[]{"","http:www.baidu.com","品牌名称不能为空"};

  String[]values2=newString[]{"三只松鼠","","品牌图标不能为空"};

  List>list=toMultiValueMaps(names,values2,values1);

  for(MultiValueMapparams:list){

  Stringmessage=params.get("message").get(0);

  ErrorMessageerror=newErrorMessage("004",message);

  mockMvc.perform(post("/goods/brands")

  .params(params))

  .andExpect(status().is(400))

  .andExpect(objectEquals(error));

  }

  }

  当测试参数校验很多的时候,重要的是集中精力排列下面的参数及提示的message:

  String[]names=newString[]{"name","logo","message"};

  String[]values1=newString[]{"","http:www.baidu.com","品牌名称不能为空"};

  String[]values2=newString[]{"三只松鼠","","品牌图标不能为空"};

consumer的测试

  consumer的单元测试不用面向消息测试,直接面向业务测试即可,举例说明,假设有如下消费者:

  /**

  订单状态变化时发送短信

  **/

  @Component

  publicclassOrderSmsMsgSenderimplementsOrderStatusChangeEvent{

  @Override

  publicvoidorderChange(OrderStatusChangeMsgorderMessage){

  //发送短信的代码

  }

  }

  则直接调用此类来测试即可:

  publicclassOrderSmsMsgSenderTestextendsBaseTest{

  @Autowire

  privateOrderSmsMsgSenderorderSmsMsgSender

  @Test

  publicvoidtestSendSms(){

  OrderStatusChangeMsgmsg=newOrderStatusChangeMsg();

  msg.setOrdersn("xxxx")

  orderSmsMsgSender.orderChange(msg);

  //执行断言,略...

  }

  }

规范

  1、测试类的包名,和相应的测试目标的类相同。

  2、测试的结果靠断言,而非system.print+肉眼

  3、单元测试中不允许出现控制台的输出(system.print)

  4、所有controller都必须提供单元测试

  5、复杂逻辑的业务类也要提供单元测试

  6、在代码请求合并之前,必须保证所有的单元测试通过(包括其他人的)

  上述就是关于Junit开发流程的内容了,想了解更多详情,可以持续关注易族智汇javashop,有任何问题,欢迎一起探讨。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

后台-系统设置-扩展变量-手机广告位-内容正文底部
留言与评论(共有 0 条评论)
   
验证码: