如何使用Nunit和RhinoMocks模拟HttpContext.Current.GetOwinContext()?

时间:2017-07-25 14:00:52

标签: c# unit-testing mocking owin rhino-mocks

my last question on Mocking the HttpContext相比,我不得不将正在测试的方法更改为

public override void OnActionExecuting(HttpActionContext actionContext)
{
    HttpContext.Current.GetOwinContext().Set("RequestGUID", NewId.NextGuid());
    base.OnActionExecuting(actionContext);
}

现在我需要弄清楚如何嘲笑 HttpContext.Current.GetOwinContext(), 所以我可以为Set()方法编写一个存根,或者通常能够测试这个特定的行。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:4)

我已阅读this article,但在您的情况下,我认为做这样的事情会有点矫枉过正..

由于GetOwinContext()返回一个接口所有你需要做的就是将这个调用与方法分开,这样做有两个问题:

  1. 测试中的方法(OnActionExecuting()归属性类所有。
  2. GetOwinContext()是一种静态方法。
  3. 我能为您提供的最佳解决方案是:

    1. 使用代码挥动工具,如MsFakes,Typemock Isolator等,而不是像RhinoMocks这样基于代理的工具。
    2. GetOwinContext()提取为虚方法,然后使用PartialMock技术(此技术通常用于抽象类):
    3. 让我们说MyCustonAttributte是你的属性:

      public class MyCustonAttributte : ActionFilterAttribute
      {
          public override void OnActionExecuting(HttpActionContext actionContext)
          {
              GetOwinContext().Set("RequestGUID", Guid.NewGuid());
              base.OnActionExecuting(actionContext);
          }
      
          public virtual IOwinContext GetOwinContext()
          {
              return HttpContext.Current.GetOwinContext();
          }
      }
      

      然后你的UT将是:

      [Test]
      public void New_GUID_should_be_added_when_OnActionExecuting_is_executing()
      {
          //arrange section:
          const string REQUEST_GUID_FIELD_NAME = "RequestGUID";
          var owinContext = MockRepository.GenerateStub<IOwinContext>();
      
          var target = MockRepository.GeneratePartialMock<MyCustonAttributte>();
      
          target.Stub(x => x.GetOwinContext())
              .Return(owinContext);
      
          //act:
          target.OnActionExecuting(new HttpActionContext());
      
          //assert section:
          owinContext.AssertWasCalled(x => x.Set(Arg<string>.Is.Equal(REQUEST_GUID_FIELD_NAME),
              Arg<Guid>.Is.NotEqual(Guid.Empty)));
      }