簡體   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