2016-04-21 135 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)); 
    } 
}