2016-01-24 33 views
0
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()永远不会调用?我如何设置应用程序内任何地方发生异常的情况?我如何编写单元测试此actionfilter

回答

0

如果在执行请求出现未处理异常则Exception属性上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()); 
} 

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

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 = ... 
      } 
     } 
    } 

单位测试

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接口嘲笑DB背景 - 在这里看到:http://aikmeng.com/post/62817541825/how-to-mock-dbcontext-and-dbset-with-moq-for-unit

+0

我会upvote当我可以感谢 – kermanoz

相关问题