代码之家  ›  专栏  ›  技术社区  ›  Eric Schneider

自定义验证器属性可以在单元测试中工作,但不能在web api控制器中工作?

  •  0
  • Eric Schneider  · 技术社区  · 8 年前

    validateMiniMaxListCountAttribute验证属性在我的单元测试中有效,但在WebAPI框架中使用时无效?

    有人有什么想法吗?

    [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; }
    }
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Nkosi    8 年前

    基于你的另一个问题,这似乎是相关的,你表明,控制器的行动看起来像。。。

    [HttpGet("{mock}")]
    public ActionResult<CoralResult> CalculateMock(CoralRequest mock)
    

    在测试中,正在发出GET请求,GET请求没有正文,但是您向请求中添加了一个正文。这意味着模型很可能没有在服务器上正确填充/绑定

    这看起来很经典 XY problem

    如果您想获取请求的主体,那么该操作很可能是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");
    }
    

    参考 Model Binding in ASP.NET Core