编写单元测试有助于代码维护。例如,在更新代码时,想要确定更新不会破坏其他代码。创建自动单元测试可以帮助确保修改代码后,所有功能都得以保留。Visual Studio 2017提供了一个健壮的单元测试框架,还可以在Visual Studio内使用其他测试框架。
1. 使用MSTest创建单元测试
下面的示例测试类库UnitTestingSamples中一个非常简单的方法。这是一个.NET标准库。当然,可以创建其他基于MSBuild的项目。类DeepThought包含TheAnswerToTheUltimateQuestionOfLifeTheUniversalAndEverything方法,该方法返回42作为结果:
public class DeepThought
{
public int TheAnswerOfTheUltimateQuestionOfLifeUniversalAndEverything() =>
42;
}
为了确保没有人改变返回错误结果的方法,创建一个单元测试。要创建单元测试,可以使用dotnet命令:
> dotnet new mstest
也可以使用Visual Studio中的Unit Test Project(.NET Core)项目模版。
开始创建第一个测试之前,最好考虑一下测试和测试项目的命名。当然,可以使用任何名称,但.NET Core团队提供了较好的命名规则,参阅:
https://github.com/aspnet/Home/wiki/Engineer_guidelines#unit-tests-ad-functional-tests
下面是规则汇总:
- 测试项目的名称是在项目名后加上Tests,例如,对于项目UnitTestingSamples,测试项目的名称是UnitTestingSamples.Tests。
- 测试类名与被测试的类名相同,后跟Test。例如,DeepThought的测试类时DeepThoughtTest。
- 单元测试方法名采用描述性的名称,例如,名称AddOrUpdateBookAsync_ThrowsForNull表示,一个单元测试调用AddOrUpdateBookAsync方法,检查传递null时它是否抛出异常。
MSTest项目包含对NuGet包Microsoft.NET.Test.Sdk、MSTest.TestAdapter和MSTest.TestFramework的引用:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UniTestingSamples\UniTestingSamples.csproj" />
</ItemGroup>
</Project>
单元测试类标有TestClass特性,测试方法标有TestMethod特性。该实现方法创建DeepThought的一个实例,并调用要测试的方法TheAnswerToTheUltimateQuestionOfLifeTheUniversalAndEverything。返回值使用Assert.AreEqual与42进行比较。如果Assert.AreEqual失败,测试就失败:
[TestClass]
public class DeepThoughtTest
{
[TestMethod]
public void ResultOfTheAnswerToTheUltimateQuestionOfLifeTheUniversalAndEverything()
{
//arrange
int expected = 42;
var dt = new DeepThought();
//act
int actual = dt.TheAnswerOfTheUltimateQuestionOfLifeUniversalAndEverything();
//assert
Assert.AreEqual(expected,actual);
}
}
单元测试由3个A定义:Arrage、Act和Assert。首先,一切都安排好了,单元测试可以开始了。在安排阶段,在第一个测试中,给变量expected分配调用要测试的方法时预期的值,调用DeepThought类的一个实例。现在准备好测试功能了。在行动阶段,调用方法。在完成行动阶段后,需要验证结果是否与预期相同。这在断言阶段使用Assert类的方法来完成。
Assert类是Microsoft.VisualStudio.TestTools.UnitTesting名称空间中MSTest框架的一部分。这个类提供了一些可用于单元测试的静态方法。默认情况下,Assert.Fail方法添加到自动创建的单元测试中,提供测试还没有实现的信息。其他一些方法有:AreNotEqual验证两个对象是否不同;IsFalse和IsTrue验证布尔结果;IsNull和IsNotNull验证空结果;IsInstanceOfType和IsNotInstanceOfType验证传入的类型。
2. 运行单元测试
使用Test Explorer,可以在解决方案中运行测试。
下图显示了一个失败的测试,列出了失败的所有细节。
要在命令行上运行测试,可以调用 dotnet test:
> dotnet test
在示例应用程序中,会得到成功的结果:
Determining projects to restore...
All projects are up-to-date for restore.
You are using a preview version of .NET. See