2017-08-09 61 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); 
    // ... 

}