控制器动作中使用的模拟方法

时间:2016-06-15 13:55:23

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

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);
 }

此测试通过succ。但是当改变控制器动作以填充像

这样的组合时
public ActionResult SomeAction(int?id)
{
   MyModel model = new MyModel();
   this.PopulatePageCombos(id);
   return View(model);
}

我在线上犯了错误.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的类型为MyModelcountryIdintrequesterIdint

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:0)

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

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

因此,在测试中,您可以创建Controller controller

而不是创建ControllerTestable 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);
}

答案 2 :(得分:0)

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

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 。这将在未设置的方法上调用编程逻辑。