.NET Core系列 :4 测试

2016.6.27 微软已经正式发布了.NET Core 1.0 RTM,但是工具链还是预览版,同样的大量的开源测试库也都是至少发布了Alpha测试版支持.NET Core, 这篇文章 The State of .Net Core Testing Today 就将各个开源测试库的目前进展进行了汇总。本文我们的目的是在我们构建我们应用程序的时候能够进行测试,如何使用XUnit结合你可以通过为你的项目添加不同的测试用例NSubstitute进行单元测试,同时对整个项目进行集成测试。这次我们使用Visual Studio 2015 Update 3进行编写 。xUnit.net是基于.NET Framework 的开源测试工具。通过xUnit.net可以针对C#/F#/VB.NET等进行单元测试。ASP.NET Core 更直接把以往的Visual Studio Unit Test Framework 说再见了,而直接使用上了xUnit.net,xUnit.net基于NUnit 。从网站或者官网上,你可以找到不少xUnit的优点,与NUnit和其他测试框架相比有一下一些优势  
         1)为每个测试方法产生一个对象实例
         2)取消了[SetUp]和[TearDown]
         3)取消了[ExpectedException]
         4)类似于Aspect的功能
         5)减少了自定义属性(Attribute)的数目
         6)采用泛型
         7)匿名委托
         8)可扩展的断言
         9)可扩展的测试方法
         10)可扩展的测试类

         了解更多关于xUnit.net可以参考这里(点击打开链接[舍弃Nunit拥抱Xunit])。

 

使用xUnit.net 单元测试

 

首先我们类似于.NET Core系列 :3 、使用多个项目 创建一个解决方案testdemo,添加一个类库项目叫做DotnetCoreLib,Library.cs 也替换为:

namespace DotnetCoreLib
{
    public class Calculator
    {
        public int Multi(int x, int y)
        {
            return x * y;
        }
    }

}

下面我们要创建一个针对DotnetCoreLib的测试项目,具体创建过程我们参照文章 https://github.com/dotnet/core-docs/tree/master/samples/core/getting-started/unit-testing-using-dotnet-test ,我们修改DotnetCoreLibTest 项目的project.json ,增加XUnit相关的nuget包引用,并修改部分配置。

 

 

还有我们设置Framework节点为 netcoreapp1.0, 依赖的xunit 和xunit.runner的包

"dependencies": {
    "dotnet-test-xunit": "2.2.0-preview2-build1029",
    "DotnetCoreLib": {
      "version": "1.0.0-*",
      "target": "project"
    },
    "xunit": "2.2.0-beta2-build3300",
    "xunit.runner.console": "2.2.0-beta2-build3300"
  }

 

Calculator接下来就开始测试我们的类库Calculator, 修改Class1.cs为CalculatorTest.cs ,

 

using DotnetCoreLib;
using Xunit;

 

namespace DotnetCoreLibTest
{
    public class CalTest
    {
        private readonly Calculator calculator;


        public CalTest()
        {
            calculator = new Calculator();
        }

 

        [Fact]
        public void OneMutiOneIsOne()
        {
            var result = calculator.Multi(1, 1);
            Assert.Equal(1, result);
        }

 

        [Theory]
        [InlineData(-1)]
        [InlineData(0)]
        [InlineData(1)]
        public void ReturnValue(int value)
        {
            var result = calculator.Multi(1,value);

            Assert.Equal(result, value);
        }
    }
}

 

上面的两个测试,我们分别用了2个特性[Fact] 和[Theory], [Fact]属性表示为一个方法的单个测试,[Theory]属性表示执行相同的代码,但是有不同的输入的参数的测试套件。[InlineData] 属性可用于指定为这些输入值。通过特性[Fact] 和[Theory],xUnit就理解了这是个测试方法,然后运行这个方法。在一个测试方法中,我们一般遵循包含三步骤的AAA模式:

  1. Arrange:为测试准备

  2. Act:运行SUT(实际测试的代码)

  3. Assert:校验结果

下面我们运行dotnet test 就可以看到结果了。

C:\Users\geffz\Documents\Visual Studio 2015\Projects\TestDemo\DotnetCoreLibTest>dotnet test
Project DotnetCoreLib (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
Project DotnetCoreLibTest (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
xUnit.net .NET CLI test runner (64-bit .NET Core win10-x64)
  Discovering: DotnetCoreLibTest
  Discovered:  DotnetCoreLibTest
  Starting:    DotnetCoreLibTest
  Finished:    DotnetCoreLibTest
=== TEST EXECUTION SUMMARY ===
   DotnetCoreLibTest  Total: 4, Errors: 0, Failed: 0, Skipped: 0, Time: 0.206s
SUMMARY: Total: 1 targets, Passed: 1, Failed: 0.

 

上面的输出我们知道已经执行了4个测试,都通过了,[Face]特性标识表示固定输入的测试用例,而[Theory]特性标识表示可以指定多个输入的测试用例,结合InlineData特性标识使用。在上面的例子里,总共使用了三次InlineData特性标识,每次设定的值都不同,在执行单元测试时,设定的值会被测试框架赋值到对应的测试方法的参数里。你可以通过为你的项目添加不同的测试用例,这样就可以让你的代码得到充分测试。

 

xUnit.net 搭配NSubstitute 进行单元测试

 

   在一个分层结构清晰的项目里,各层之间依赖于事先约定好的接口。在多人协作开发时,大多数人都只会负责自己的那一部分模块功能,开发进度通常情况下也不一致。当某个开发人员需要对自己的模块进行单元测试而依赖的其他模块还没有开发完成时,则需要对依赖的接口通过Mock的方式提供模拟功能,从而达到在不实际依赖其他模块的具体功能的情况下完成自己模块的单元测试工作。这时我们通常需要有一个单元测试模拟类库,一直以来,开发者对 mocking 类库的语法的简洁性有强烈的需求,NSubstitute 试图满足这一需求。简单明了的语法可以让我们将重心放在测试本身,而不是纠缠在测试替代实例的创建和配置上。NSubstitute 已尝试将最常用的操作需求简单化、易用化,并支持一些不常用的或探索性的功能,与此同时还尽可能地将其语法向自然语言靠近。关于NSubstitute的更详细信息请往 NSubstitute完全手册索引。

 

NSubstitute 已经发布2.0 RC版本支持.NET Core。引入NSubstitute 相关nuget包:

我们把Calculator 类重构下提取出接口ICalculator:

    public interface ICalculator
    {
        int Multi(int x, int y);
    }

 

我们可以让NSubstitute来创建类型实例的替代实例,可以创建诸如 Stub、Mock、Fake、Spy、Test Double 等,但当我们只是想要一个能有一定程度控制的替代实例时,为什么我们要困扰于此呢?我们可以告诉被创建的替代实例,当方法被调用时返回一个值:

     [Fact]
      public void Test_GetStarted_ReturnSpecifiedValue()
      {
          ICalculator calculator = Substitute.For<ICalculator>();
          calculator.Multi(1, 2).Returns(2);

          int actual = calculator.Multi(1, 2);
          Assert.Equal(2, actual);
      }

下面我们运行dotnet test 就可以看到结果了,增加了上面的2个用例,关于NSubstitute的更详细信息请往 NSubstitute完全手册索引。

 

集成测试

上面我们只是对逻辑进行了单元测试。对于Asp.Net Core项目,还需要模拟在网站部署的情况下对各个请求入口进行测试。NET Core 可为快速轻松集成测试提供非常棒的支持。

TestServer 类为 ASP.NET Core 中的集成测试执行大部分繁重操作,Microsoft.AspNetCore.TestHost 包中具有此类。本节内容来自于MSDN杂志《 ASP.NET Core - 实际的 ASP.NET Core MVC 筛选器》,这些集成测试不需要数据库或 Internet 连接或运行的 Web 服务器。它们如同单元测试一样快速简单,但最重要的是,它们允许你在整个请求管道中测试 ASP.NET 应用,而不只是控制器类中的孤立方法。建议尽可能编写单元测试,并针对无法单元测试的行为退回到集成测试,但使用此类高性能方式在 ASP.NET Core 中运行集成测试是非常棒的。

 

通过在一个工程里同时模拟了服务端(TestServer)和客户端(HttpClient)的通信,从而达到了整体测试WebApi接口的目的,相关的代码放在https://github.com/ardalis/GettingStartedWithFilters/tree/master/IntegrationTests 。文章对ASP.NET CORE MVC的筛选器进行测试,由于很难通过编写单元测试来测试此类场景,但是可以通过ASP.NET Core 的集成测试来达到相同的目的。

using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using Filters101;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;

 

namespace IntegrationTests
{
    public class AuthorsControllerTestBase
    {
        protected HttpClient GetClient()
        {
            var builder = new WebHostBuilder()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>()
                .UseEnvironment("Testing");
            var server = new TestServer(builder);
            var client = server.CreateClient();

            // client always expects json results
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            return client;
        }
    }
}

 

 

using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Filters101.Models;
using Newtonsoft.Json;
using Xunit;

namespace IntegrationTests.AuthorsController
{
    public class Get : AuthorsControllerTestBase
    {
        private readonly HttpClient _client;

        public Get()
        {
            _client = base.GetClient();
        }

        [Theory]
        [InlineData("authors")]
        [InlineData("authors2")]
        public async Task ReturnsListOfAuthors(string controllerName)
        {
            var response = await _client.GetAsync($"/api/{controllerName}");
            response.EnsureSuccessStatusCode();
            var stringResponse = await response.Content.ReadAsStringAsync();
            var result = JsonConvert.DeserializeObject<IEnumerable<Author>>(stringResponse).ToList();

            Assert.Equal(2, result.Count());
            Assert.Equal(1, result.Count(a => a.FullName == "Steve Smith"));
            Assert.Equal(1, result.Count(a => a.FullName == "Neil Gaiman"));
        }
    }
}

此案例中的客户端是标准的 System.Net.Http.HttpClient,你可以使用它向服务器发出请求,正如同通过网络一样。但因为所有请求都在内存中进行,所以测试极其快速可靠。在cmd窗口执行单元测试,查看测试结果

相关文章:

  • .NET Core系列 : 1、.NET Core 环境搭建和命令行CLI入门

  • .NET Core系列 : 2 、project.json 这葫芦里卖的什么药

  • .NET Core系列 :3 、使用多个项目


原文地址:http://www.cnblogs.com/shanyou/p/5770840.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java高效字符串首字母大小写转换

通过找到一个移动ASCII的方式来处理字符串首字母大小写的问题 我们都知道在ascii 码表中 a的ASCIII码值是65而A的ASCII码值是 97 两个之间的差值是 32&#xff0c;所以&#xff0c;如果我们需要把一个小写字母转化成大写字母&#xff0c;那么我们只需要把这个 char 字符的asci…

java面向对象高级分层实例_BaseDao

package bdqn.studentSys.Dao; /*** 数据库帮助类* author Administrator**/ import java.sql.*; public class BaseDao {Connection connnull;PreparedStatement psnull;ResultSet rsnull;//连接数据库public void getConnection(){try {Class.forName("com.microsoft.sq…

Myeclipse 创建web项目的一些基本操作

上面是tomcat的工作路径 什么是工作路径呢&#xff1f; 启动tomcat 就开始监听8080端口了 在浏览器数据url 请求web请求 就会显示出index.jsp 上篇博客中有讲到更改tomcat端口 但是在运行中的修改是不会生效的 必须停止 再重启 怎么引入jar包&#xff1f; 支持中文 这样…

Java制作VCARD

转载自 Java制作VCARD 简介: vCard是电子名片的文件格式标准。它一般附加在电子邮件之后,但也可以用于其它场合(如在互联网上相互交换)。vCard可包含的信息有:姓名、地址资讯、电话号码、URL,logo,相片等。——摘自维基百科https://zh.wikipedia.org/wiki/VCardvCard规范容许…

java反射机制的简单使用和优缺点

java反射机制的使用 一、反射是什么&#xff1f; JAVA反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够获取这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意一个方法和属性&#xff1b;这种动态获取类信息以及动态调…

有关技术分享

有人说&#xff0c;如果你想掌握好一门技术&#xff0c;那么最好的方式就是去当老师&#xff0c;去教会别人这门技术。在教别人的过程中&#xff0c;你必须要去深入的了解这门技术的方方面面&#xff0c;同时还要思考怎么才能让别人理解。每一个做过的人都知道&#xff0c;这要…

不可重复 幻读

幻读和不可重复读的区别 2014年09月15日 20:51:27 阅读数&#xff1a;26195 MySQl MySql默认的隔离级别为Repeatable Read&#xff0c;因此只会出现幻读的情况。 幻读 事务在插入已经检查过不存在的记录时&#xff0c;惊奇的发现这些数据已经存在了&#xff0c;之前的检测…

java生成验证码

转载自 java生成验证码 源码&#xff1a; package seed.lee.image;import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random;import javax.imageio.ImageIO; …

ASP.NET Core 中文文档 第三章 原理(5)错误处理

原文&#xff1a;Error Handling作者&#xff1a;Steve Smith翻译&#xff1a;谢炀&#xff08;Kiler)校对&#xff1a;高嵩(jack2gs)、何镇汐 当你的ASP.NET应用发生错误的时候, 你可以采用本文所述的各种方法来处理这些问题。 配置错误处理页面 你在 Startup 类的 Configure(…

java面向对象高级分层实例_接口类

package bdqn.studentSys.Dao;import java.util.List;import bdqn.studentSys.entity.Student;/*** 学生表的接口* author Administrator**/ public interface StudentDao {//查询所有的学生public List<Student> getAllStudent();//修改学生信息public int UpdateStuden…

杀死进程

-- 杀死进程端口 netstat -aon|findstr "8086" taskkill /PID 9160 /f

菜鸟学Java(六)——简单验证码生成(Java版)

转载自 菜鸟学Java&#xff08;六&#xff09;——简单验证码生成(Java版)验证码大家都知道&#xff0c;它的作用也不用我多说了吧。如果不太清楚请参见百度百科中的解释&#xff0c;一般验证码的生成就是随机产生字符&#xff08;数字、字母或者汉字等&#xff09;&#xff0…

对象集合中如何用对象的某个属性给对象排序?

这是在工作中遇到的一个问题。用到的持久层技术是mybatis-plus&#xff0c;它里面自带的条件对象wrapper&#xff0c;我们可以通过wrapper.orderByDesc()或者wrapper.orderByAsc()给我们list中的对象排序。 但是问题来了&#xff0c;如果公司在基于这个框架的基础上写了一个通用…

你知道C#中的Lambda表达式的演化过程吗

那得从很久很久以前说起了&#xff0c;记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂。 委托的使用 例一&#xff1a; 什么是委托&#xff1f; 个人理解&#xff1a;用来传递方法的类型。&#xff08;用来传递数字的类型有int、float、double&#xff0c;用…

拦截第三方快递物流 ,console控制台打印正常 ,浏览器显示正常 ,传至后台乱码

使用 apache.http. 可以解决 压缩的json文件 浏览器会自动解压但我们的后台不会package com.zjyouth.utils;import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.…

java面向对象高级分层实例_数据库操作类

package bdqn.studentSys.Dao.impl; /**** 学生表的数据库操作类*/ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List;import bdqn.studentSys.Dao.BaseDao; import bdqn.studentSys.Dao.StudentDao; import bdqn…

shiro-权限概述

一、什么是权限 权限管理&#xff0c;一般根据系统的安全设置或安全规则&#xff0c;用户可以且只能访问自己被授予的资源。只要有用户名和密码&#xff0c;就一定会存在权限。 二、权限分类 访问权限 作为一个使用者或是访问者&#xff0c;你能够被允许看到的那些资源。 数…

ASP.NET Core Kestrel 中使用 HTTPS (SSL)

在ASP.NET Core中&#xff0c;如果在Kestrel中想使用HTTPS对站点进行加密传输&#xff0c;可以按照如下方式 申请证书 这一步就不详细说了&#xff0c;有免费的和收费的&#xff0c;申请完成之后会给你一个*.pfx结尾的文件。 添加NuGet包 nuget中查找然后再程序中添加引用Micro…

idea

war 发布 war explord 开发

Java最小堆解决TopK问题

转载自 Java最小堆解决TopK问题 TopK问题是指从大量数据&#xff08;源数据&#xff09;中获取最大&#xff08;或最小&#xff09;的K个数据。 TopK问题是个很常见的问题&#xff1a;例如学校要从全校学生中找到成绩最高的500名学生&#xff0c;再例如某搜索引擎要统计每天…