2016-04-21 131 views
1

我有一個表單過程,我想用Moq進行單元測試。 我有單元測試的工作代碼獲取WebApi的方法,它的工作很好,但我不知道如何寫一篇文章MVC控制器中的無效方法。MVC Moq單元測試無效方法

我想測試ModelState.IsValid和異常如果無效返回。

控制器

public class HomeController : Controller 
{ 
    private IEditDataRepository _editDataRepository; 

    public HomeController() 
    { 
     //Default Constructor 
    } 

    //Dependency Injection using Unity.MVC5 NuGet Package 
    public HomeController(IEditDataRepository editDataRepository) 
    { 
     _editDataRepository = editDataRepository; 
    } 

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public void Edit([Bind(Include = "Field1,Field2")] FormViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      _editDataRepository.Edit(model); 
     } 
     else 
     { 
      throw new HttpException(400, "ModelState Invalid"); 
     } 
    } 
} 

REPOSITORY

public class EditDataRepository : IEditDataRepository, IDisposable 
{ 
    private DBEntities db = new DBEntities(); 

    public void Edit(FormViewModel model) 
    {    
     db.MyProcedure(model.Field1,model.Field2); 
    } 

    private bool disposed = false; 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.disposed) 
     { 
      if (disposing) 
      { 
       db.Dispose(); 
      } 
     } 
     this.disposed = true; 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 
} 

單元測試

我能做的設置有點在這裏,但我之後我不知道。 如何檢查ModelState.IsValid而無效(返回異常)?

[TestMethod] 
public void TestSomething() 
{ 
    //Arrange 
    var mockRepository1 = new Mock<IEditDataRepository>(); 

    mockRepository1 
     .Setup(x => x.Edit(It.IsAny<FormViewModel>())); 
    HomeController controller = new HomeController(mockRepository1.Object); 

    //Act 
    controller.Edit(It.IsAny<FormViewModel>()); 

    //Assert 

} 
+0

只是傳遞一個無效的'FormViewModel'到編輯操作。 –

+0

或手動設置模型狀態:http://stackoverflow.com/questions/3822873/how-to-mock-modelstate-isvalid-using-the-moq-framework –

+0

好奇,爲什麼你對控制器的操作無效? – Nkosi

回答

1
[TestMethod] 
public void TestSomething() 
{ 
    //Arrange 
    var mockRepository1 = new Mock<IEditDataRepository>(); 

    mockRepository1 
     .Setup(x => x.Edit(It.IsAny<FormViewModel>())); 
    HomeController controller = new HomeController(mockRepository1.Object); 
    controller.ModelState.AddModelError("error", "invalid model"); 

    //Act/Assert 
    var ex = Assert.Throws<HttpException>(() => controller.Edit(It.IsAny<UTCFormViewModel>())); 

    Assert.Equal(400, ex.ErrorCode); 
} 

另外,我建議你不實現物/敲定您Repository模式。除非它真的是非託管資源,似乎並非如此。 This msdn link有更多的細節。

+0

太好了。謝謝你。有沒有對有效的ModelState進行測試,還是應該用其他方法替換void方法? – madvora

+0

有效模型的測試可以通過檢查你的模擬來驗證。它將被稱爲模型有效的情況 –

0

我以爲我會分享我與之一起去的路線。我決定不返回void,而是決定返回一個HttpStatusCode。 我已經很熟悉如何測試。

控制器

public class HomeController : Controller 
{ 
    private IEditDataRepository _editDataRepository; 

    //Dependency Injection using Unity.MVC5 NyGet Packages 
    public HomeController(IEditDataRepository editDataRepository) 
    { 
     _editDataRepository = editDataRepository; 
    } 

    // GET: 
    public ActionResult Index() 
    { 
     return View(); 
    } 

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Edit([Bind(Include = "Field1,Field2")] FormViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      _editDataRepository.Edit(model); 
      return new HttpStatusCodeResult(HttpStatusCode.OK); 
     } 
     else 
     { 
      throw new HttpException(400, "ModelState Invalid"); 
     } 
    } 
} 

REPOSITORY

public class EditDataRepository : IEditDataRepository, IDisposable 
{ 
    private DBEntities db = new DBEntities(); 

    public void Edit(FormViewModel model) 
    {    
     db.MyProcedure(model.Field1,model.Field2); 
    } 

    private bool disposed = false; 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.disposed) 
     { 
      if (disposing) 
      { 
       db.Dispose(); 
      } 
     } 
     this.disposed = true; 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 
} 

單元測試

[TestClass] 
public class HomeControllerTests 
{ 
    /// <summary> 
    /// Tests the Edit method is run 
    /// </summary> 
    [TestMethod] 
    public void Edit_Method_Is_Run() 
    { 
     //Arrange 
     var mockRepository = new Mock<IEditDataRepository>(); 
     mockRepository 
      .Setup(x => x.Edit(It.IsAny<FormViewModel>())); 
     HomeController controller = new HomeController(mockRepository.Object); 

     //Act 
     controller.Edit(It.IsAny<FormViewModel>()); 

     //Assert 
     mockRepository.VerifyAll(); 
    } 

    [TestMethod] 
    public void Edit_Returns_OK() 
    { 
     //Arrange 
     var mockRepository = new Mock<IEditDataRepository>(); 
     mockRepository 
      .Setup(x => x.Edit(It.IsAny<FormViewModel>())); 
     HomeController controller = new HomeController(mockRepository.Object); 

     //Act    
     var response = controller.Edit(It.IsAny<FormViewModel>()); 

     //Assert 
     Assert.IsInstanceOfType(response, typeof(HttpStatusCodeResult)); 
     var httpResult = response as HttpStatusCodeResult; 
     Assert.AreEqual(200, httpResult.StatusCode); 
    } 

    /// <summary> 
    /// Tests the Edit method throws exception 
    /// </summary> 
    [TestMethod] 
    [ExpectedException(typeof(HttpResponseException))] 
    public void Edit_Returns_Exception() 
    { 
     var mockRepository = new Mock<IEditDataRepository>(); 
     mockRepository 
      .Setup(x => x.Edit(It.IsAny<FormViewModel>())) 
      .Throws(new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest))); 
     HomeController controller = new HomeController(mockRepository.Object); 

     //Act    
     var response = controller.Edit(It.IsAny<FormViewModel>()); 

     //Assert 
     Assert.IsInstanceOfType(response, typeof(HttpResponseException)); 
    } 
}