【问题标题】:MVC Moq Unit Test Void MethodMVC Moq 单元测试无效方法
【发布时间】:2016-08-14 23:06:15
【问题描述】:

我有一个要使用 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

}

【问题讨论】:

  • 只需将无效的FormViewModel 传递给编辑操作。
  • 或者手动设置模型状态:stackoverflow.com/questions/3822873/…
  • 很好奇,为什么你对控制器的操作无效?
  • Nkosi - 不太确定。我想在我真正知道自己在做什么之前,我只是在处理旧代码。你认为这应该是什么,ActionResult?我想我这样做是因为它只是在运行更新,我只需要知道它是否失败。

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


【解决方案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 有更多详情。

【讨论】:

  • 太棒了。谢谢你。是否对有效的 ModelState 进行了测试,还是应该用其他方法替换 void 方法?
  • 可以通过检查您的模型来验证有效模型的测试。如果模型有效,就会调用它
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    相关资源
    最近更新 更多