Asp.net mvc 如何使用asp.net mvc进行模拟测试

Asp.net mvc 如何使用asp.net mvc进行模拟测试,asp.net-mvc,asp.net-mvc-3,unit-testing,appharbor,Asp.net Mvc,Asp.net Mvc 3,Unit Testing,Appharbor,我正在编写一个我一直部署到appharbor的应用程序。我现在很难构建我的项目,因为我已经扩展了我的测试。我认为问题在于我正在使用db初始值设定项用测试种子数据填充数据库。这些测试在我的本地机器上通过,但一旦我在appharbor上部署测试,这些测试就会失败。我怀疑我需要模拟数据,但我不确定如何做到这一点。作为一个例子,这里有一个控制器测试,我对我的一个动作方法进行了测试 控制器 // GET: /Lead/Url // TODO: Add optional url parame

我正在编写一个我一直部署到appharbor的应用程序。我现在很难构建我的项目,因为我已经扩展了我的测试。我认为问题在于我正在使用db初始值设定项用测试种子数据填充数据库。这些测试在我的本地机器上通过,但一旦我在appharbor上部署测试,这些测试就会失败。我怀疑我需要模拟数据,但我不确定如何做到这一点。作为一个例子,这里有一个控制器测试,我对我的一个动作方法进行了测试

控制器

    // GET: /Lead/Url
    // TODO: Add optional url parameters
    public ActionResult Url(string pfirstname, string plastname, string phone, int leadsource)
    {

        var lead = new Lead();
        //store 
        lead.parent_FirstName = pfirstname;
        lead.parent_LastName = plastname;
        lead.parent_Phone = phone;
        lead.LeadSourceID = leadsource;
        lead.AgentID = 1;

        if (ModelState.IsValid)
        {
            leadRepository.InsertLead(lead);
            leadRepository.Save();
            ViewBag.Message = "Success";
        }

        return View(lead);
    }

    //
    // POST: /Lead/URL       
    [HttpPost, ActionName("Url")]
    public ActionResult Url(Lead lead)
    {
        return View();
    }
单元测试

[TestMethod]
    public void LeadUrl()
    {
        //ARRANGE
        ILeadRepository leadrepository = new LeadRepository(new LeadManagerContext());
        Database.SetInitializer<LeadManagerContext>(new LeadManagerInitializer());
        LeadController controller = new LeadController(leadrepository);

        //ACT
        ViewResult result = controller.Url("Brad", "woods","465-456-4965",1) as ViewResult;
        var lead = (Lead)result.ViewData.Model;

        //ASSERT
       Assert.AreEqual("Success" ,result.ViewBag.Message);
        /*check for valid data */
       Assert.AreEqual("Brad", lead.parent_FirstName);

    }
[TestMethod]
public-void-LeadUrl()
{
//安排
ILeadRepository leadrepository=新leadrepository(新LeadManagerContext());
SetInitializer(新的LeadManagerInitializer());
LeadController=新的LeadController(leadrepository);
//表演
ViewResult结果=controller.Url(“Brad”,“woods”,“465-456-4965”,1)作为ViewResult;
变量lead=(lead)result.ViewData.Model;
//断言
Assert.AreEqual(“成功”,result.ViewBag.Message);
/*检查有效数据*/
Assert.AreEqual(“Brad”,lead.parent_名字);
}

请有人解释一下,为了改进这样的代码并使其在app harbor上再次成功运行,我接下来需要做什么?

事实上,您还没有验证控制器与其依赖项(存储库)之间的交互。这是最重要的部分-控制器应该将您的
Lead
对象传递给存储库。然后调用
Save
(还要考虑工作单元模式)

此外,您还应该单独测试控制器,只有这样,您才能确保控制器测试失败是控制器的问题,而不是
LeadRepository
LeadManagerInitializer
的问题

// Arrange
Lead expected = CreateBrad();    
var repository = new Mock<ILeadRepository>();
LeadController controller = new LeadController(repository.Object);    
// Act
ViewResult result = (ViewResult)controller.Url("Brad", "woods", "465-456", 1);
// Assert      
Lead actual = (Lead)result.ViewData.Model;
// All fields should be equal, not only name
Assert.That(actual, Is.EqualTo(expected));
Assert.AreEqual("Success", result.ViewBag.Message);
// You need to be sure, that expected lead object passed to repository
repository.Verify(r => r.InsertLead(expected));
repository.Verify(r => r.Save());
此外,您还应覆盖
Equals
方法进行
Lead
实例比较:

public class Lead
{
   // your current code here

   public override bool Equals(object obj)
   {
       Lead other = obj as Lead;
       if (other == null)
           return false;

       return other.parent_FirstName == parent_FirstName &&
              other.parent_LastName == parent_LastName &&
              // compare other properties here
              other.AgentID == AgentID;
   }

   // also override GetHashCode method
}

顺便问一下,为什么不将
引导
对象传递给您的操作方法(通过POST消息)?

您必须存根您的存储库。最简单的方法是使用mocking框架(我更喜欢),并对每个方法进行存根

类似这样的东西(用于最低起订量):

var repository=newmock();
Setup(r=>r.InsertLead(It.IsAny());
//举起,冲洗,重复
LeadController=新的LeadController(repository.Object);

您的存储库存根是什么意思?用一个完全满足测试需要的实现来代替它。如果您还没有听说过它,那么,很可能您在单元测试中做了一些非常错误的事情。我强烈推荐阅读。听起来我的思路是对的。我现在把书放在桌子上,想把这一切弄清楚。好吧,这有点道理。运行此程序需要什么程序包?是最小起订量吗?是的,最小起订量。这是非常简单和强大的。我得到了一个错误的帖子。今天我将尝试将该代码转移到帖子中。我很惊讶,但它可以在静止状态下工作。你确定这行代码吗?断言(实际的,等于(预期的));这是针对NUnit测试框架的。对于MSTest,您可以使用
Assert.AreEqual(实际、预期)
。别忘了在你的
Lead
课程中重写
Equals
方法!此外,POST和GET动词是向后的:将数据发布到服务器,然后从服务器获取数据。您的GET方法正在保存数据。是的,我知道这一点,但感谢您的提醒。
public class Lead
{
   // your current code here

   public override bool Equals(object obj)
   {
       Lead other = obj as Lead;
       if (other == null)
           return false;

       return other.parent_FirstName == parent_FirstName &&
              other.parent_LastName == parent_LastName &&
              // compare other properties here
              other.AgentID == AgentID;
   }

   // also override GetHashCode method
}
var repository = new Mock<ILeadReporisory>();
repository.Setup(r => r.InsertLead(It.IsAny<Lead>()));
//raise, rinse, repeat

LeadController controller = new LeadController(repository.Object);