我想针对给定MyModelDTO
值测试我的控制器方法。
这是我的控制器 Post 方法(简化):
[HttpPost]
public ActionResult Post([FromBody] MyModelDTO itemDTO)
{
ModelState.Remove($"{nameof(itemDTO)}.{nameof(itemDTO.Id)}");
if (!ModelState.IsValid)
{
return BadRequest();
}
//rest of code
}
我的MyModelDTO
班级:
public class MyModelDTO
{
[IsNotEmpty(ErrorMessage = "Guid Id Is Empty")]
public Guid Id { get; set; }
}
我的习惯ValidationAttribute
:
public class IsNotEmptyAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value == null) return false;
var valueType = value.GetType();
var emptyField = valueType.GetField("Empty");
if (emptyField == null) return true;
var emptyValue = emptyField.GetValue(null);
return !value.Equals(emptyValue);
}
}
我的问题是如何测试 ModelState 的自定义属性的自动验证?
这是我尝试过的:
[Test] public void Post_WhenCalled_ShouldReturnPostResult()
{
using (var mock = AutoMock.GetLoose())
{
//Arrange
var controller = mock.Create<MyController>();
//Act
ActionResult actionResult = controller.Post(new MyModelDTO());
//Assert...
}
}
单元测试工作正常(控制器应该MyModelDTO
使用没有参数的参数Id
),但看起来它并没有真正模拟 ModelState 的自动验证过程。我怎么知道这个?因为当我尝试做一个缺少Id
财产的邮递员时,它会导致"Guid Id Is Empty"
消息。它甚至不会在断点处停止。
作为模型绑定过程的一部分,模型验证在控制器之外被调用。这意味着您无法在控制器单元测试中真正测试它。相反,在测试控制器时,如果您想根据模型状态验证控制器的行为,您基本上已经必须模拟模型状态。
您可以在这里做两件事:如果您只想测试您的验证逻辑,那么最好的方法就是直接调用ValidationAttribute
。所以你不测试控制器,而是测试你的属性。
您可以简单地实例化您的属性,然后运行该Validate
方法来测试其行为。只需传递您要验证的对象的实例,您就可以验证它抛出的异常。
另一种解决方案是进行完整的集成测试。这样,您就不会对控制器进行单元测试,而是测试整个请求管道,包括控制器和模型验证。对于特定场景,这是确保一切端到端运行的最佳方式。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句