MVC Moq单元测试无效方法

时间:2016-04-21 15:57:00

标签: c# asp.net-mvc unit-testing asp.net-mvc-4 moq

我有一个表格帖子,我希望用Moq进行单元测试。 我有单元测试的工作代码获取WebApi方法很好,但我不知道如何在MVC控制器中写一个void方法的帖子。

我想测试ModelState.IsValid,如果无效则返回异常。

CONTROLLER

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

UNIT TESTS

我可以在这里做一些设置,但之后我不确定。 如何检查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

}

2 个答案:

答案 0 :(得分: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);
}

另外,我建议您不要在存储库中实现Dispose / Finalize模式。除非它真的不受管理的资源似乎并非如此。 This msdn link有更多详情。

答案 1 :(得分:0)

我以为我会分享这条路线。我决定不返回void并决定返回一个HttpStatusCode。 我已经熟悉了如何测试它。

<强> CONTROLLER

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

UNIT TESTS

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