【问题标题】:Mocking method used in controller action控制器动作中使用的模拟方法
【发布时间】:2016-06-15 13:55:23
【问题描述】:
public ActionResult SomeAction(int?id)
 {
      MyModel model = new MyModel();
      return View(model);
 }

 [Test]
 public void Can_Open_SomeAction()
 {
     // controller is already set inside `SetUp` unit step.
     ViewResult res = this.controller.SomeAction() as ViewResult;
     var model = result.Model as MyModel;
     Assert.IsNotNull(model);
 }

此测试成功通过。但是当更改控制器操作以填充组合时,例如

public ActionResult SomeAction(int?id)
{
   MyModel model = new MyModel();
   this.PopulatePageCombos(id);
   return View(model);
}

我在 this.PopulatePageCombos(id); 线上遇到错误

Object reference is not set

那么,如何在单元测试中模拟这个 PopulatePageCombos 方法?

更新:

 public ActionResult SomeAction(int?id)
 {
    MyModel model = new MyModel();
    this.PopulatePageCombos(model.Id, 100);
    return View(model);
 }

更新 2:

PopulatePageCombos (model, countryId, requesterId);

其中model 的类型为MyModelcountryId 的类型为intrequesterId 的类型为int

【问题讨论】:

  • this.PopulatePageCombos(id) 做什么/使用什么?它依赖于测试期间不存在的东西。确定那是什么,然后您可以决定如何测试您的被测方法 (MUT)
  • @Nkosi,实际上它使用了两个参数,我刚刚更新了我的问题。是否可以在 nunit SetUp 方法中模拟这个以避免使用任何外部帮助器?
  • 你误解了我的评论。查看PopulatePageCombos 方法的主体。方法定义是什么样的。此外,您更新后的帖子不再使用 id 参数,因此现在传递给它的内容都无关紧要,结果应该是相同的。

标签: c# .net asp.net-mvc razor nunit


【解决方案1】:

您可以创建一个助手class PopulatePageCombosHelper 并将PopulatePageCombos 方法封装在其中。所以SomeAction 方法看起来像

public PopulatePageCombosHelper populatePageHelper;

public ActionResult SomeAction(int?id)
{
   MyModel model = new MyModel();
   populatePageHelper.PopulatePageCombos(id);
   return View(model);
}

那么你可以模拟populatePageHelper

[Test]
public void Can_Open_SomeAction()
{
    // controller is already set inside `SetUp` unit step.
    var populatePageHelperMock = new Mock<PopulatePageCombosHelper>();
    controller.populatePageHelper = populatePageHelperMock;
    ViewResult res = this.controller.SomeAction() as ViewResult;
    var model = result.Model as JobCreate;

    //...
    Assert.IsNotNull(model);
}

【讨论】:

    【解决方案2】:

    您可以将PopulatePageCombos 方法设为虚拟并在派生类ControllerTestable 中覆盖它并测试ControllerTestable

    public class ControllerTestable : Controller
    {
        public bool IsCalled = false;
        public override ViewResult SomeAction()
        {
            IsCalled = true;
            return null;
        }
    }
    

    因此,在测试中,您可以创建ControllerTestable controller,而不是创建Controller controller

    [Setup]
    public void SetUp () 
    {
        var controller = new ControllerTestable();
        //...
    }
    
    [Test]
    public void Can_Open_SomeAction()
    {
        // controller is already set inside `SetUp` unit step.
        ViewResult res = this.controller.SomeAction() as ViewResult;
        var model = result.Model as JobCreate;
    
        //...
        Assert.IsTrue(controller.IsCalled);
        Assert.IsNotNull(model);
    }
    

    【讨论】:

      【解决方案3】:

      您可以部分模拟控制器。有:

      public virtual void PopulatePageCombos(int? id)
      {
          throw new NullReferenceException();
      }
      
      public ActionResult SomeAction(int? id)
      {
          MyModel model = new MyModel();
      
          this.PopulatePageCombos(id);
      
          return View(model);
      }
      

      然后你设置方法 PopulatePageCombos 来做任何事情:

      public class Default1ControllerTests
      {
          private Mock<Default1Controller> controllerMock;
      
          [SetUp]
          public void SetUp()
          {
              this.controllerMock = new Mock<Default1Controller>() { CallBase = true };
      
              this.controllerMock.Setup(m => m.PopulatePageCombos(It.IsAny<int?>())).Callback(() => { });
          }
      
          [Test]
          public void Can_Open_SomeAction()
          {
              // controller is already set inside `SetUp` unit step.
              ViewResult res = this.controllerMock.Object.SomeAction(null) as ViewResult;
      
              var model = res.Model as MyModel;
      
              Assert.IsNotNull(model);
          }
      }
      

      重要的是声明虚拟模拟方法并在模拟创建时指定CallBase = true。这将调用未设置方法的编程逻辑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-28
        • 1970-01-01
        相关资源
        最近更新 更多