专业的东莞网站推广,物流网络规划名词解释,素材网站下载,wordpress 模板目录前言上次#xff0c;我们介绍了因为DTO的“不变性”#xff0c;应该用record来定义DTO。今天#xff0c;我们来说明用record来定义DTO的另一个好处。问题首先#xff0c;我们实现一个Controler#xff0c;代码如下:[ApiController]
[Route([controller])]
pub… 前言上次我们介绍了因为DTO的“不变性”应该用record来定义DTO。今天我们来说明用record来定义DTO的另一个好处。问题首先我们实现一个Controler代码如下:[ApiController]
[Route([controller])]
public class UserController : ControllerBase
{private readonly IMediator _mediator;public UserController(IMediator mediator){this._mediator mediator;}[HttpGet({id})]public async TaskUserDto GetById(int id){var request new GetUserByIdQuery { Id id };var result await this._mediator.Send(request);return result;}
}public class UserDto
{public int Id { get; set; }public string Name{ get; set; }
}public class GetUserByIdQuery : IRequestUserDto
{public int Id { get; set; }
}
这里IRequestT可以认为是DTO。然后我们编写测试用例[Fact]
public async void Test1()
{var mediatorMock new MockIMediator();var request new GetUserByIdQuery { Id 1};var expectedUser new UserDto { Id 1, Name My IO };mediatorMock.Setup(x x.Send(request, default(CancellationToken))).Returns(Task.FromResult(expectedUser));var controller new UserController(mediatorMock.Object);var result await controller.GetById(1);Assert.Equal(expectedUser, result);
}
我们Mock了IMediator期望它执行Send后返回expectedUser。看起来都没有问题但是测试执行失败调试代码可以看到传递的参数是正确的但是返回值是null这说明实际没有命中mediatorMock.Setup中的方法。这是为什么呢原因原因其实是x.Send(request, default(CancellationToken))表示必须完全匹配才能返回指定的结果但是request和GetById方法中创建的request其实是2个不同的实例.NET并不认为它们相等。虽然可以修改mediatorMock.Setup方法来修复测试。但对于我来说属性值完全相同的DTO应该就是相等的可以让类实现值相等性来解决public class GetUserByIdQuery : IRequestUserDto
{public int Id { get; set; }public override bool Equals(object obj) this.Equals(obj as GetUserByIdQuery);public bool Equals(GetUserByIdQuery p){if (p is null){return false;}if (Object.ReferenceEquals(this, p)){return true;}if (this.GetType() ! p.GetType()){return false;}return Id p.Id;}public override int GetHashCode() Id.GetHashCode();
}
但是为每个DTO重写Equals和GetHashCode也不是个事。record的相等性其实更简单的解决方法是修改定义如下public record GetUserByIdQuery : IRequestUserDto
{public int Id { get; set; }
}
你会发现测试通过了。这是因为record在设计上就具备创建具有值相等数据类型的能力编译器会自动生成样板代码结论在本文中我们介绍了通过使用record类型可以大大简化定义实现值相等性DTO的代码量。如果你觉得这篇文章对你有所启发请关注我的个人公众号”My IO“记住我