繁体   English   中英

MVC Moq 单元测试无效方法

[英]MVC Moq Unit Test Void Method

我有一个程序的表单发布,我想用 Moq 进行单元测试。 我有用于单元测试的工作代码 Get WebApi 方法很好用,但我不确定如何在 MVC 控制器中为 void 方法写一篇文章。

我想测试 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");
        }
    }
}

存储库

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

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

另外,我建议您不要在您的存储库上实现 Dispose/Finalize 模式。 除非它确实是非托管资源,但情况似乎并非如此。 此 msdn 链接有更多详细信息。

我想我会分享我的路线。 我决定不返回 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");
        }
    }
}

存储库

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM