关于单元测试的思考--Asp.Net Core单元测试最佳实践

发表于:2018-9-29 10:23

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

 作者:李玉宝    来源:博客园

分享:
  在我们码字过程中,单元测试是必不可少的。但在从业过程中,很多开发者却对单元测试望而却步。有些时候并不是不想写,而是常常会碰到下面这些问题,让开发者放下了码字的脚步:
  这个类初始数据太麻烦,你看:new MyService(new User("test",1), new MyDAO(new Connection(......)),new ToManyPropsClass(......) .....) 。我:。。。
  这个代码内部逻辑都是和Cookie有关,我单元测试不好整啊,还是得启动到浏览器里一个按钮一个按钮点。
  这个代码内部读了配置文件,单元测试也不能给我整个配置文件啊?
  这个代码主要是验证WebAPI入口得模型绑定,必须得调用一次啊?
  这些问题确实存在,但它们阻止不了我们那颗要写单元测试的心。单元测试的优点很多,你或许可以不管。但至少能让你从那些需要在浏览器里点击10多下的操作里解脱出来。本文从一个简单的逻辑测试出发,慢慢拉开测试的大幕,让你爱上测试。文章主要是传播一些单元测试的理念,其次才是介绍asp.net core中的单元测试。
  本文使用的环境为asp.net core 2.1 webapi,代码可以直接下载:https://github.com/yubaolee/DotNetCoreUnitTestSamples 为了方便阅读,以一个最简单的逻辑为例:
  public class UserService{
  public bool CheckLogin(UserInfo user)
  {
  return user.Name == user.Password;  //登录逻辑,为了看着舒服,少点
  }
  }
  public class UserInfo{
  public string Name { get; set; }
  public string Password { get; set; }
  }
  测试的WebAPI控制器如下:
  public class ValuesController : ControllerBase
  {
  private UserService _service;
  public ValuesController(UserService service)
  {
  _service = service;
  }
  [HttpGet]
  [Route("checklogin")]
  public bool CheckLogin([FromQuery]UserInfo user)
  {
  return _service.CheckLogin(user);
  }
  }
  都已准备完毕,那么,开始我们的表演吧:
  普通业务的单元测试
  public class TestService
  {
  private UserService _service;
  [SetUp]
  public void Init()
  {
  var server = new TestServer(WebHost.CreateDefaultBuilder().UseStartup<Startup>());
  _service = server.Host.Services.GetService<UserService>();
  }
  [Test]
  public void TestLogin()
  {
  bool result = _service.CheckLogin(new UserInfo { Name = "yubao", Password = "yubao" });
  Assert.IsTrue(result);
  }
  }
  在做业务测试过程中要善于使用注入功能,而不是使用new对象的方式,比如这里的Host.Services.GetService,防止出现new MyService(new User("test",1), new MyDAO(new Connection(......)),new ToManyPropsClass(......) .....)这种尴尬。用的越多你就越能体会这种做法的好处。我在openauth.net中使用的是autofac的AutofacServiceProvider。
  测试Controller
  很多时候我们需要测试顶层的controller(八成是controller里混的有业务逻辑)。这时我们可以快速的写出下面的测试代码:
  public class TestController
  {
  private ValuesController _controller;
  [SetUp]
  public void Init()
  {
  var server = new TestServer(WebHost.CreateDefaultBuilder().UseStartup<Startup>());
  _controller = server.Host.Services.GetService<ValuesController>();
  }
  [Test]
  public void TestLogin()
  {
  bool result = _controller.CheckLogin(new UserInfo{Name = "yubao",Password = "yubao"});
  Assert.IsTrue(result);
  }
  }
  这段代码在JAVA spring mvc框架下是没有问题的,但在asp.net core 中,你会发现:
 
  获取不到controller?spring mvc的理念就是万物皆服务,哪怕是一个controller也是一个普通的服务。但微软不喜欢这样,默认时它要掌控controller的生死(The Subtle Perils of Controller Dependency Injection in ASP.NET Core MVC 有人在声讨微软了)。所以我们不能通过普通的ServicCollection来注入和获取它,除非你指明Controller As Service,如下:
   
   上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

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

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

沪ICP备05003035号

沪公网安备 31010102002173号