我该如何为这个actionfilter编写单元测试

时间:2016-01-24 16:57:18

标签: unit-testing asp.net-web-api2 moq xunit

public MyContext _db;
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
   if (_db == null || !_db.ChangeTracker.HasChanges())
   {
      return;
   }

   try
   {
      _db.SaveChanges();
   }
   catch
   {
   }
}

这是我的wep api项目的动作过滤器。每个请求注入此过滤器的_db上下文对象。我的观点是在服务层完成所有处理之后调用SaveChanges()方法一次。我的问题是如何测试这个过滤器?我怎样才能模仿任何控制器或服务层中可能发生的异常情况,以及异常抛出saveChanges()从未调用过?如何在应用程序内的任何位置设置异常发生的情况?

2 个答案:

答案 0 :(得分:1)

上周,我一直在为我的WebAPI 2动作过滤器做同样的事情。

我有一个动作过滤器验证我的ModelState,如果有任何错误,它会抛出一个包含200个HTTPcode的错误列表。

动作如下:

 public class ModelValidationActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var modelState = actionContext.ModelState;

            if (!modelState.IsValid)
            {
                actionContext.Response = ...
            }
        }
    }

UNIT TEST

var httpControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/someUri")
                {
                    Content = new ObjectContent(typeof(MyModel),
                        new MyModel(), new JsonMediaTypeFormatter())
                },
                RequestContext = new HttpRequestContext()
            };

            httpControllerContext.Request = new HttpRequestMessage();
            httpControllerContext.Request.SetConfiguration(new HttpConfiguration());
            var httpActionContext = new HttpActionContext { ControllerContext = httpControllerContext };

            var filter = new ModelValidationActionFilterAttribute();

            httpActionContext.ModelState.AddModelError("*", "Invalid model state");

            // act
            filter.OnActionExecuting(httpActionContext);

            // assert
            httpActionContext.Response.ShouldNotBe(null);
            httpActionContext.Response.ShouldBeOfType(typeof (HttpResponseMessage));
            var result = httpActionContext.Response.Content.ReadAsStringAsync().Result;
            BaseServiceResponse<object> resultResponse =
                JsonConvert.DeserializeObject<BaseServiceResponse<object>>(result);

            resultResponse.Data.ShouldBe(null);
            resultResponse.Messages.Count.ShouldBe(1);
            resultResponse.Messages.First().Description.ShouldBe("Invalid model state");

在您的情况下,您需要使用IDbContext接口模拟数据库上下文 - 请参阅此处:http://aikmeng.com/post/62817541825/how-to-mock-dbcontext-and-dbset-with-moq-for-unit

答案 1 :(得分:0)

如果在执行请求时发生未处理的异常,则actionExecutedContext上的Exception属性将包含该异常。这是框架的一部分,而不是您需要测试的内容。在测试中,您可以手动设置[Fact] public void Saves_data_on_failure() { var mockDbContext = new Mock<IDbContext>(); var myAttribute = new MyAttribute(mockDbContext.Object); var executionContext = new HttpActionExecutedContext { Exception = new Exception("Request failed.") }; myAttribute.OnActionExecuted(executionContext); mockDbContext.Verify(d => d.SaveChanges()); } 属性,并断言属性采取正确的操作。

output = (TextView) view.findViewById(R.id.jData);
    JsonObjectRequest jor = new JsonObjectRequest(Request.Method.GET, loginURL, null,
            new Response.Listener<JSONObject>() {


                @Override
                public void onResponse(JSONObject response) {

                    try{

                        JSONArray ja = response.getJSONArray("posts");


                        for(int i=0; i < ja.length(); i++){

                            JSONObject jsonObject = ja.getJSONObject(i);


                            String title = jsonObject.getString("title");
                            String text = jsonObject.getString("text");

                            data += "Blog Number "+(i+1)+" \n title= "+title  +" \n text= "+ text +" \n\n\n\n ";

                        }

                        output.setText(data);
                    }catch(JSONException e){e.printStackTrace();}
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Volley","Error");

                }
            }
    );
    requestQueue.add(jor);

您可能还想考虑是否要为所有类型的异常保存数据。数据可能处于无效/未知状态。