使用 MS Test 与 .NET Core API






4.33/5 (2投票s)
本文档描述了如何使用 MS Test 测试您的 .NET Core API。
引言
.NET Core 现在是 .NET 世界中任何 Web 应用程序开发的默认标准。然而,在每个应用程序开发过程中,对您的代码进行单元测试非常重要。
幸运的是,.NET Core 对 MS Test 提供了出色的支持。本文档描述了如何使用 MS Test 编写 API 的单元测试用例。
为什么选择 MS Test,而不是 xUnit?
xUnit 是一个优秀的测试框架,但我发现它缺少我们在使用 MS Test 编写测试用例多年来习惯的一些功能。xUnit 的主要限制之一是,它没有类似于 AssemblyInitialize
的功能,而 AssemblyInitialize
可以在执行任何测试用例之前用来初始化任何内容。
我使用 AssemblyInitialize
来注册我的 DI 以及其他全局初始化。如果您像我一样喜欢初始化测试项目,那么 MS Test 是默认选择。
.NET Core 对 MS Test 提供了出色的支持。
Using the Code
我正在使用 Visual Studio 2017 创建我的 API 项目并编写 MS Test 用例。请按照以下步骤编写 MS Test 用例
- 将一个类型为“单元测试项目 (.NET Core)”的新项目添加到您的解决方案中。
- 添加对解决方案中其他项目的引用。
- 添加 nuget 包 "
Microsoft.AspNetCore.TestHost
"。如果您想使用模拟,请添加 "Moq
" nuget 包。 - 将您的主 API 项目中的 Startup.cs 复制到您的测试项目中。我将其重命名为 "TestStartup.cs",只是为了避免意外修改主 Startup.cs。
- 在您的测试项目中添加一个 TestInitializer.cs(您可以将类重命名为您喜欢的任何名称)。
- 添加启动测试服务器和注册模拟存储库的逻辑。
[TestClass] public class TestInitializer { public static HttpClient TestHttpClient; public static Mock<IEmployeeRepository> MockEmployeeRepository; [AssemblyInitialize] public static void InitializeTestServer(TestContext testContext) { var testServer = new TestServer(new WebHostBuilder() .UseStartup<TestStartup>() // this would cause it to use StartupIntegrationTest class // or ConfigureServicesIntegrationTest / ConfigureIntegrationTest // methods (if existing) // rather than Startup, ConfigureServices and Configure .UseEnvironment("IntegrationTest")); TestHttpClient = testServer.CreateClient(); } public static void RegisterMockRepositories(IServiceCollection services) { MockEmployeeRepository = (new Mock<IEmployeeRepository>()); services.AddSingleton(MockEmployeeRepository.Object); //add more mock repositories below } }
- 从 TestStartup.cs 的 "
ConfigureServices
" 中调用方法来初始化您的存储库。public IServiceProvider ConfigureServices(IServiceCollection services) { .... //Mock your repositories. TestInitializer.RegisterMockRepositories(services); .... }
- 编写您的第一个测试用例
[TestClass] public class TestEmployee { [TestMethod] public void TestGetAllEmployees() { var mockEmps = new List<Employee>(); mockEmps.Add(new Employee { EmpId = 1, FirstName = "F1", LastName = "L1", Email = "F1.L1@tt.com" }); mockEmps.Add(new Employee { EmpId = 2, FirstName = "F2", LastName = "L2", Email = "F2.L2@tt.com" }); var employeeRepositoryMock = TestInitializer.MockEmployeeRepository; employeeRepositoryMock.Setup (x => x.GetEmployees()).Returns(Task.FromResult(mockEmps)); var response = TestInitializer.TestHttpClient.GetAsync("api/Employees").Result; var resp = response.Content.ReadAsStringAsync().Result; var responseData = JsonConvert.DeserializeObject<List<Employee>>(resp); Assert.AreEqual(3, responseData.Count); Assert.AreEqual(mockEmps[0].EmpId, responseData[0].EmpId); } }
- 现在您可以调试/运行您的测试用例并在测试资源管理器中查看结果。
值得关注的点
控制器中不应该包含任何调用您的业务逻辑层的其他代码,这是一个好的做法。人们倾向于只对他们的业务逻辑编写测试用例,因为他们认为控制器没有代码。我更喜欢编写调用控制器的测试用例,因为它遍历了整个层次结构。
您可以从下面的 github 链接下载示例代码。
一个主要的限制是 Visual Studio 不支持 .NET Core 项目的代码覆盖率,详情请参见此 链接。 看起来 Visual Studio 2017 的 Update 3 支持代码覆盖率,但我还没有机会下载和试用 Update 3。获取 .NET Core 项目代码覆盖率的一种选择是使用开源 opencover。