public class UserController { private readonly IUserService _userService; public UserController(IUserService userService) { _userService = userService; } [HttpGet("{id}")] public IActionResult GetUser(int id) { var user = _userService.GetUser(id); if (user == null) { return NotFound(); } else { ... } } }
在举办单位测试的时候, 可以利用 Moq 对 _userService.GetUser 举办模仿返回值
[Fact] public void GetUser_ShouldReturnNotFound_WhenCannotFoundUser() { // arrange // 新建一个IUserService的mock工具 var mockUserService = new Mock<IUserService>(); // 利用moq对IUserService的GetUs要领举办mock: 当入参为233时返回null mockUserService .Setup(it => it.GetUser(233)) .Return((User)null); var controller = new UserController(mockUserService.Object); // act var actual = controller.GetUser(233) as NotFoundResult; // assert // 验证挪用过userService的GetUser要领一次,且入参为233 mockUserService.Verify(it => it.GetUser(233), Times.AtMostOnce()); }
4.3 AutoFixture官方客栈
https://github.com/AutoFixture/AutoFixture
AutoFixture是一个假数据填充库,旨在最小化3A中的 arrange 阶段,使开拓人员更容易建设包括测试数据的工具,从而可以更专注与测试用例的设计自己。
根基用法
直接利用如下的方法建设强范例的假数据
[Fact] public void IntroductoryTest() { // arrange Fixture fixture = new Fixture(); int expectedNumber = fixture.Create<int>(); MyClass sut = fixture.Create<MyClass>(); // act int result = sut.Echo(expectedNumber); // assert Assert.Equal(expectedNumber, result); }
上述示例也可以和测试框架自己团结,好比xUnit
[Theory, AutoData] public void IntroductoryTest( int expectedNumber, MyClass sut) { // act int result = sut.Echo(expectedNumber); // assert Assert.Equal(expectedNumber, result); }
5. 实践中团结Visual Studio的利用Visual Studio提供了完备的单位测试的支持,包罗运行. 编写. 调试单位测试。以及查察单位测试包围率等。
5.1 如安在Visual Studio中运行单位测试 5.2 如安在Visual Studio中查察单位测试包围率如下成果需要Visual Studio 2019 Enterprise版本,社区版不带这个成果。
如何查察包围率
在测试窗口下,右键相应的测试组 点
点击如下的"阐明代码包围率"
6. 实践中常见场景的Mock主要
6.1 DbSet利用EF Core进程中,如何mock DbSet是一个绕不外的坎。
要领一
参考如下链接的答复举办自行封装
https://stackoverflow.com/questions/31349351/how-to-add-an-item-to-a-mock-dbset-using-moq
要领二(推荐)
利用现成的库(也是基于上面的方法封装好的)
客栈地点:
https://github.com/romantitov/MockQueryable
利用典型
// 1. 测试时建设一个模仿的List<T> var users = new List<UserEntity>() { new UserEntity{LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012")}, ... }; // 2. 通过扩展要领转换成DbSet<UserEntity> var mockUsers = users.AsQueryable().BuildMock(); // 3. 赋值给给mock的DbContext中的Users属性 var mockDbContext = new Mock<DbContext>(); mockDbContext .Setup(it => it.Users) .Return(mockUsers);
6.2 HttpClient利用RestEase/Refit的场景
假如利用的是 RestEase 可能 Refit 等级三方库,详细接口的界说本质上就是一个interface,所以直接利用moq举办要领mock即可。
而且发起利用这种方法。
IHttpClientFactory
假如利用的是.Net Core自带的 IHttpClientFactory 方法来请求外部接口的话,可以参考如下的方法对 IHttpClientFactory 举办mock
https://www.thecodebuzz.com/unit-test-mock-httpclientfactory-moq-net-core/
6.3 ILogger由于ILogger的LogError等要领都是属于扩展要领,所以不需要出格的举办要领级此外mock。
针对平时的一些利用场景封装了一个辅佐类, 可以利用如下的辅佐类举办Mock和Verify