.NET重构—单元测试重构(2)

发表于:2013-10-10 11:28

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:wangqingpei557    来源:51Testing软件测试网采编

  这是两个用例,用来对AddOrder方法进行测试,里面都包含了一条Order testOrder = new Order() 这样的测试数据的构造;Order实体是一个比较简单的对象,属性也就只有两个,但是真实环境中不会这么简单,会有几十个字段都需要进行测试验证,再加上N多个用例,会使相同的代码变的很多;
  那么我们同样需要将这部分的代码提取出来放到基类中去,适当的留有空间让用例中修改的特殊的字段;
  完整的实体构造:
  Order testOrder = this.InitNormalOrder();
  Order testOrder = this.InitNormalOrder();
  测试OrderId为空的逻辑,需要手动设置为String.Empty:
  <STRONG>Order testOrder = this.InitNormalOrder();
  testOrder.OrderId = string.Empty; </STRONG>
  Order testOrder = this.InitNormalOrder();
  testOrder.OrderId = string.Empty; 这样慢慢的就会形成抗变化的测试代码结构,尽管一开始很别扭,将一些直观的对象提取出来放入一眼看不见的地方是有点不太舒服,但是长远看来值得这么做;
  3】LINQ表达式的重构写法(将必要的LINQ写成普通的Function穿插在LINQ表达式中)
  在使用LINQ语法编写代码的时候,现在发现最大的问题就是单元测试不太方便,LINQ写起来很方便,确实是个很不错的编程思想,在面对集合类型的操作时确实是无法形容的优雅,但是面对单元测试的问题需要解决才行,所以需要我们平衡一下在什么情况下需要将LINQ表达式替换成普通的Function来支持;
  LINQ在面对集合类型的时候,能发挥很大的作用;不仅在Linq to Object中,在其他的Linq to Provider中都能在LINQ中找到了合适的使用之地;比如在对远程Service进行LINQ设计的时候,我们都是按照这样的方式进行编写,但是就怕LINQ中带有逻辑判断的表达式,这个时候就会在单元测试中总是无法覆盖到的情况出现,所以就需要将它提取出来使用普通的函数进行替代;
  我们来继续看一下如果使用提取出来的函数解决链式的判断,还是使用上面的OrderService为例:
  public Order SelectByOrderId(string orderId)
  {
  List<Order> orders = new List<Order>()
  {
  new Order(){ OrderId="123", SubmitDT=DateTime.Now.AddDays(1)},
  new Order(){ OrderId="234"}
  };
  var list = orders.Where(order => order.OrderId == orderId && order.SubmitDT > DateTime.Now);
  if (list.Count() > 0)
  return list.ToList()[0];
  return null;
  }
  public Order SelectByOrderId(string orderId)
  {
  List<Order> orders = new List<Order>()
  {
  new Order(){ OrderId="123", SubmitDT=DateTime.Now.AddDays(1)},
  new Order(){ OrderId="234"}
  };
  var list = orders.Where(order => order.OrderId == orderId && order.SubmitDT > DateTime.Now);
  if (list.Count() > 0)
  return list.ToList()[0];
  return null;
  }

  这是一个根据OrderId获取Order实例的方法,纯粹为了演示;首先构造了一个测试集合,然后使用了Where扩展方法来选择集合中满足条件的Order;我们的重点是Where中的条件,条件的第一个表达式很简单而第二个表达式是SubmitDT必须大于当前的日期,还会有很多类似这样的判断,这样测试起来很困难,而且很难维护,所以我们有必要将他们提取出来;

  public Order SelectByOrderId(string orderId)
  {
  List<Order> orders = new List<Order>()
  {
  new Order(){ OrderId="123", SubmitDT=DateTime.Now.AddDays(1)},
  new Order(){ OrderId="234"}
  };
  var list = orders.Where(order => IfOrderSubmitAndOrderId(order, orderId));
  if (list.Count() > 0)
  return list.ToList()[0];
  return null;
  }
  private bool IfOrderSubmitDt(Order order)
  {
  return order.SubmitDT > DateTime.Now;
  }
  private bool IfOrderSubmitAndOrderId(Order order, string orderId)
  {
  return order.OrderId == orderId && this.IfOrderSubmitDt(order);
  }
  public Order SelectByOrderId(string orderId)
  {
  List<Order> orders = new List<Order>()
  {
  new Order(){ OrderId="123", SubmitDT=DateTime.Now.AddDays(1)},
  new Order(){ OrderId="234"}
  };
  var list = orders.Where(order => IfOrderSubmitAndOrderId(order, orderId));
  if (list.Count() > 0)
  return list.ToList()[0];
  return null;
  }
  private bool IfOrderSubmitDt(Order order)
  {
  return order.SubmitDT > DateTime.Now;
  }
  private bool IfOrderSubmitAndOrderId(Order order, string orderId)
  {
  return order.OrderId == orderId && this.IfOrderSubmitDt(order);
  }

  其实这很像企业架构模式中的规约模式,将规则对象化后就能随便的控制他们,当然这里是提取出方法,如果是大型企业级项目对这些易变化的点是需要抽取出来的;
  总之遇到这样的情况就使用简单的提取方法的方式将复杂的逻辑提取出来,这也是《重构》中的重构策略的首要的模式;

32/3<123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号