c# - 自定义验证器属性在单元测试中有效,但在 WebAPI 控制器中无效?
问题描述
ValidateMinMaxListCountAttribute 验证属性在我的单元测试中有效,但在 WebAPI 框架中使用时无效?
例如,在单元测试中,“isValid”返回 true,但在控制器中却失败了。我猜是某种序列化问题?
有人有想法么?
[TestCategory("ServiceTests")]
[TestMethod]
public void CallServiceCalc()
{
var client = new RestClient();
client.BaseUrl = new Uri("https://localhost:44379");
client.Authenticator = new HttpBasicAuthenticator("eric.schneider", "password");
var request = new RestRequest();
request.Resource = "api/Calculation/Calculate";
CoralRequest coralReq = new CoralRequest();
coralReq.ModelId = 1;
coralReq.ModelName = "2018";
coralReq.BasePlan = new BeneifitsPlanInputs();
coralReq.Plans.Add(new BeneifitsPlanInputs());
request.AddBody(coralReq);
ValidateMinMaxListCountAttribute va = new ValidateMinMaxListCountAttribute(1, 999);
bool isValid = va.IsValid(coralReq.Plans);
IRestResponse response = client.Execute(request);
Assert.IsTrue(response.StatusCode == System.Net.HttpStatusCode.OK, "Should not be ok");
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class ValidateMinMaxListCountAttribute : ValidationAttribute
{
public ValidateMinMaxListCountAttribute(int minimum, int maximum)
{
this.MinimumCount = minimum;
this.MaximumCount = maximum;
}
public int MinimumCount { get; set; }
public int MaximumCount { get; set; }
public override bool IsValid(object value)
{
var list = value as ICollection;
if (list != null)
{
if (list.Count > MaximumCount) { return false; }
if (list.Count < MinimumCount) { return false; }
return true;
}
return false;
}
}
public class CoralRequest
{
public CoralRequest()
{
this.Plans = new List<BeneifitsPlanInputs>();
}
/// <summary>
///
/// </summary>
[ValidateMinMaxListCount(1, 99, ErrorMessage = "Must have between 1 and 99 plans")]
public IList<BeneifitsPlanInputs> Plans { get; set; }
}
解决方案
根据您似乎相关的其他问题之一,您表明控制器操作看起来像......
[HttpGet("{mock}")]
public ActionResult<CoralResult> CalculateMock(CoralRequest mock)
在测试中,正在发出 GET 请求,GET 请求没有 BODY,但您在请求中添加了一个。这意味着模型很可能没有在服务器上正确填充/绑定
这看起来像一个经典的XY 问题
如果您想获取请求的 BODY,则该操作很可能是 POST 请求,并且应重构该操作以明确说明应从何处获取数据。
[Route("api/[controller]")]
public class CalculationController: Controller {
//POST api/Calculation/Calculate
[HttpPost("[action]")]
public ActionResult<CoralResult> Calculate([FromBody]CoralRequest model) {
if(ModelState.IsValid) {
CoralResult result = new CoralResult();
//...do something with model and populate result.
return result;
}
return BadRequest(ModelState);
}
}
现在应该更接近集成测试中尝试的内容
[TestCategory("ServiceTests")]
[TestMethod]
public void CallServiceCalc() {
var client = new RestClient();
client.BaseUrl = new Uri("https://localhost:44379");
client.Authenticator = new HttpBasicAuthenticator("eric.schneider", "password");
var request = new RestRequest(Method.POST); //<-- POST request
request.Resource = "api/Calculation/Calculate";
request.AddHeader("content-type", "application/json");
CoralRequest coralReq = new CoralRequest();
coralReq.ModelId = 1;
coralReq.ModelName = "2018";
coralReq.BasePlan = new BeneifitsPlanInputs();
coralReq.Plans.Add(new BeneifitsPlanInputs());
request.AddJsonBody(coralReq); //<-- adding data as JSON to body of request
IRestResponse response = client.Execute(request);
Assert.IsTrue(response.StatusCode == System.Net.HttpStatusCode.OK, "Should be HttpStatusCode.OK");
}
模型绑定器现在应该能够在绑定模型并将其传递给操作后验证模型。
ASP.NET Core 中的参考模型绑定
推荐阅读
- c# - WaitOne 什么时候执行非框架代码?
- android - Oreo:startService() 在后台调用时不会抛出 IllegalStateException
- javascript - 选项标签中的动态选项在JavaScript中使用带有html标签的'For循环'?
- c++ - 在 C++ 中,创建“n”个对象的推荐方法是什么,其中 n 是用户定义的。我怎样才能做到这一点?
- r - 如何在 bookdown::gitbook 中使用自定义 pandoc HTML 模板
- html - 图像不在页面中间水平居中
- firebase - 火力基地 | 使用 Firebase 控制台以 CSV 格式导出收集数据
- javascript - 我应该如何解析 Cheerio 中的复杂元素
- javascript - JS/PHP:在 Outlook 中撰写电子邮件并添加附件
- google-cloud-platform - 谷歌计算引擎,附加磁盘不工作