简体   繁体   English

Moq的Nunit测试

[英]Nunit Testing with Moq

I recently started learning Unit Test in MVC and used NUnit Framework for Test Cases. 我最近开始学习MVC中的单元测试,并使用NUnit Framework来测试用例。 My problem is, i cannot understand for what should i write Test case. 我的问题是,我不明白我应该写什么测试用例。 Imagine i have CRUD operation and i want to Test them, so what should be my Test case condition. 假设我有CRUD操作,并且想测试它们,那么我的测试用例情况应该是什么。

Here is my Interface class: 这是我的接口类:

public interface IUserRepository 
{ 
    //Creating Single User Records into database using EF.
    bool CreateUser(tbl_Users objUser);

    //Updating Single User Records into database using EF.
    void UpdateUser(tbl_Users objUser);

    //Deleting Single User Records from database using EF.
    bool DeleteUser(long IdUser);
}

Here is my Repository Class: 这是我的存储库类:

public class UserRepository : IUserRepository
{
    DBContext objDBContext = new DBContext();      

    /// <summary>
    /// Creating new User Record into Database
    /// </summary> 
    /// <param name="objUser"></param>
    public bool CreateUser(tbl_Users objUser)
    {
        bool blnResult = false;
        objUser.MiddleName = string.IsNullOrEmpty(objUser.MiddleName) ? string.Empty : objUser.MiddleName.Trim();
        objUser.Photo = string.Empty;
        objUser.Approved = false;
        objUser.CreatedDate = DateTime.Now;
        objUser.DeleteFlag = false;
        objUser.UpdBy = 0;
        objUser.UpdDate = DateTime.Now;
        objDBContext.tbl_Users.Add(objUser);
        blnResult = Convert.ToBoolean(objDBContext.SaveChanges());
        return blnResult;
    }

    /// <summary>
    /// Updating existing User Record into Database
    /// </summary> 
    /// <param name="objUser"></param>
    public void UpdateUser(tbl_Users objUser)
    {
        objUser.MiddleName = string.IsNullOrEmpty(objUser.MiddleName) ? string.Empty : objUser.MiddleName.Trim();
        objUser.Approved = true;
        objUser.UpdBy = objUser.IdUser;
        objUser.UpdDate = DateTime.Now;
        objDBContext.Entry(objUser).State = EntityState.Modified;
        objDBContext.SaveChanges();
    }

    /// <summary>
    /// Deleting existing User Record from Database
    /// </summary> 
    /// <param name="IdUser"></param>
    public bool DeleteUser(long IdUser)
    {
        bool blnResult = false;
        tbl_Users objUser = objDBContext.tbl_Users.Where(x => x.IdUser == IdUser).Single();
        objUser.ConfirmPassword = objUser.Password;
        objUser.UpdDate = DateTime.Now;
        objUser.DeleteFlag = true;
        blnResult = Convert.ToBoolean(objDBContext.SaveChanges());
        return blnResult;
    }        
}

And Here is My Controller class 这是我的控制器类

public class UserController : Controller
{
    tbl_Users objUser = new tbl_Users();
    UserRepository Repository = new UserRepository();        

    [ValidateAntiForgeryToken]
    [HttpPost]
    public ActionResult Create(tbl_Users objUser)
    {
        if (ModelState.IsValid)
        {
            try
            {
                Repository.CreateUser(objUser);
                return RedirectToAction("Update", "User");
            }
            catch
            {
                return View();
            }
        }
        return View();
    }       

    [ValidateAntiForgeryToken]
    [HttpPost]
    public ActionResult Update(tbl_Users objUser)
    {
        Repository.UpdateUser(objUser);
        return View();
    }

    public ActionResult Delete(long IdUser = 0)
    {
        bool blnResult = Repository.DeleteUser(IdUser);
        if (blnResult)
        {
            return View("Delete");
        }
        else
        {
            return View();
        }
    }
}

Here are Test cases which i tried to Execute using Moq 这是我尝试使用Moq执行的测试用例

[TestFixture]
public class UserControllerTest
{
    UserController Controller;

    [SetUp]
    public void Initialise()
    {
        Controller = new UserController();
    }       

    [Test]
    public void DeleteTest()
    {
        var ObjUser = new Mock<IUserRepository>();

        ObjUser.Setup(X => X.DeleteUser(It.IsAny<long>())).Returns(true);

        var Result = ObjUser.Object.DeleteUser(1);
        Assert.That(Result, Is.True);
    }        

    [Test]
    public void CreateTest()
    {
        tbl_Users User = new tbl_Users();
        Mock<IUserRepository> MockIUserRepository = new Mock<IUserRepository>();
        MockIUserRepository.Setup(X => X.CreateUser(It.IsAny<tbl_Users>())).Returns(true);

        var Result = MockIUserRepository.Object.CreateUser(User);

        Assert.That(Result, Is.True);
    }         

    [TearDown]
    public void DeInitialise()
    {
        Controller = null;
    }
}

Can anyone tell me, how to Write test cases for above Controller Action Method with brief description about test cases using Moq. 谁能告诉我,如何使用上述Moq编写有关上述Controller Action Method的测试用例,并简要说明测试用例。

you have a couple of problems. 你有几个问题。 the first is that you have not tested your controller, you have tested your mock. 首先是您尚未测试控制器,而您已经测试了模拟程序。 The second is that your controller creates it's own user repository. 第二个是您的控制器创建了自己的用户存储库。 this means that you can't provide a mock user repository in order to test, even if you were testing it. 这意味着即使您正在测试,也无法提供模拟用户存储库来进行测试。

The solution to the first on is to test the controller, by calling its methods and asserting the results, however you'll have solve the second one before you can do that in your tests. 第一种方法的解决方案是通过调用控制器的方法并声明结果来测试控制器,但是您必须先解决第二种方法,然后才能在测试中进行操作。

To solve the second one you'll need to apply the dependency inversion principal and pass your IUserRepository implementation into your controller (via the constructor ideally). 要解决第二个问题,您将需要应用依赖关系反转主体并将IUserRepository实现传递到控制器中(理想情况下是通过构造函数)。

you could change your controller to have a constructor like this: 您可以将控制器更改为具有如下构造函数:

public class UserController : Controller
{
    tbl_Users objUser = new tbl_Users();
    IUserRepository Repository; 

    public UserController(IUserRepository userRepository)
    {
         Repository = userRepository;
    }   

    ...etc    
}

then you can change your tests to be more like this: 那么您可以将测试更改为如下所示:

[TestFixture]
public class UserControllerTest
{ 
    [Test]
    public void DeleteTest()
    {
        var ObjUser = new Mock<IUserRepository>();

        ObjUser.Setup(X => X.DeleteUser(It.IsAny<long>())).Returns(true);

        var Result = new UserController(ObjUser.Object).Delete(1);
        Assert.That(Result, //is expected view result with expected model);
        Assert.That(ObjUser.Verify(), Is.True);        
    }        

    [Test]
    public void CreateTest()
    {
        tbl_Users User = new tbl_Users();
        Mock<IUserRepository> MockIUserRepository = new Mock<IUserRepository>();
        MockIUserRepository.Setup(X => X.CreateUser(It.IsAny<tbl_Users>())).Returns(true);

        var Result = var Result = new UserController(ObjUser.Object).Create(User);;

        Assert.That(Result, //is a view result with expected view model);
        Assert.That(ObjUser.Verify(), Is.True); 
    }         
}

now you are testing the actual controller and checking it returns the right view and that it interacts with the mock repository in the expected way 现在,您正在测试实际的控制器,并检查它是否返回了正确的视图,并以预期的方式与模拟存储库进行了交互

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

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