2017-08-09 34 views
2

我正在学习使用Moq来测试我的控制器,但我不确定如何绕过来自控制器的数据层调用。说我有一个像下面这样的方法。我会采取什么方法来测试像这样的简单控制器?如何使用Moq绕过数据层?

[HttpPost] 
public ActionResult SomeController(SomeModel model) 
{ 
    if(ModelState.IsValid) 
    { 
     // Perform some manipulation on modeldata 
     model.Value++; 

     // Upload Model, Get ID 
     model.Id = MyDataLayer.UploadToDb(model); 
    } 
    return View(model); 
} 
+2

您需要使用接口抽象出您的数据层。并在控制器的contstructor中注入数据层的实现。然后实现可以是moq'd版本或实际实现 – KiwiPiet

+0

要引用HotFuzz(指向@KiwiPiet):“他说了什么”。 – code4life

+1

提供示例中的MyDataLayer是静态的还是局部变量? – Nkosi

回答

2

事情是这样的:

interface IMyDataLayer 
{ 
    int UploadToDb(SomeModel model); 
} 
class MyDataLayer : IMyDataLayer 
{ 
    public int UploadToDb(SomeModel model) 
    { 
     // Implementation ... 
    } 
} 
class MyController : Controller 
{ 
    private readonly IMyDataLayer _datalayer; 
    public MyController(IMyDataLayer datalayer) 
    { 
     _datalayer = _datalayer; 
    } 

    [HttpPost] 
    public ActionResult SomeAction(SomeModel model) 
    { 
     if(ModelState.IsValid) 
     { 
      // Perform some manipulation on modeldata 
      model.Value++; 

      // Upload Model, Get ID 
      model.Id = _datalayer.UploadToDb(model); 
     } 
     return View(model); 
    } 
} 

然后你可以用最小起订量来创建IMyDataLayer的模拟。

+0

显示创建模拟并将其注入SUT的示例 – Nkosi

+0

好吧,只是认为它会帮助OP。他们问如何使用起订量来做到这一点?你所做的是展示了他们如何重构他们的代码以允许依赖注入,而不一定如何用最小起订量 – Nkosi

1

我使用moq实现了KiwiPet的解决方案,如下所示。

[TestMethod()] 
public void MyTestMethod() 
{ 
    // Create test input data 
    SomeModel TestModel = new SomeModel(); 
    TestModel.Value = 1; 

    // Create mocked data layer 
    var FakeDataLayer = new Mock<IMyDataLayer>(); 
    FakeDataLayer.Setup(x => x.UploadToDb(It.IsAny<SomeModel>()).Returns(TestValueIWantReturned); 

    // Create controller using fake data service 
    var controller = new MyController(FakeDataLayer.Object); 

    // Controller function call 
    var result = controller.SomeAction() as ViewResult; 

    // Assert stuff 
    Assert.IsNotNull(result); 
    Assert.IsNotNull(result.Model); 
    // ... 

}