如何使用EF SaveChanges对MVC控制器进行单元测试

时间:2014-04-13 13:34:45

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

下面是一个带Post方法的控制器。如何在不保存对数据库的更改的情况下针对CREATE方法编写单元测试?

我正在尝试针对我的控制器编写测试,以便当其他开发人员更改代码时,它不会破坏我的功能(我在Create方法上有一些功能,以便现在保持简单)。

public class AdministratorController : Controller
{
  private IUnitOfWork _uow;

[HttpPost]
public ActionResult Create(MyModel model)
{
    ViewBag.id = model.Id;

    if (model.FirstName == model.LastName)
    {
        ModelState.AddModelError("", "Cannot have same first name and last name.");
    }


    if (ModelState.IsValid)
    {
        MyClass record = new MyClass();

        record.SAFirstName = model.FirstName;
        record.SALastName = model.LastName;
        record.SATitle = model.Title;
        record.SAEmail = model.EmailAddress;

        record.Since = DateTime.Now;

        _uow.AdministratorRepository.AddRecord(record);
        _uow.SaveChanges();
        return RedirectToAction("Index", "Administrator");
    }

    return View(model);
}

}

2。)我的UOW看起来像这样:

public class UnitOfWork:IUnitOfWork {     private readonly MasterContext _context;

public UnitOfWork(MasterContext context)
{
    _context = context;
}

public UnitOfWork()
{
    _context = new MasterContext();
}

public void SaveChanges()
{
    _context.SaveChanges();
}

private IAdministratorRepository _Repo;

public IAdministratorRepository AdministratorRepository
{
    get
    {
        if (this._Repo == null)
        {
            this._Repo = new IAdministratorRepository(_context);
        }
        return _Repo;
    }

}

3)我的AdministratorRepository构造函数如下:

    private readonly MasterContext _context;

    public AdministratorRepository(MasterContext context)
    {
        _context = context;
    }

2 个答案:

答案 0 :(得分:2)

您需要能够在控制器中注入假/模拟IUnitOfWork。最简单的方法是在控制器上创建一个内部构造函数,它接受伪对象并创建一个属性,该属性可以创建新实例或返回现有实例。

private IUnitOfWork _uow;
private IUnitOfWork UnitOfWork
{
    get
    {
        _uow = _uow ?? new UnitOfWork();
        return _uow;
    }
}

public AdministratorController() {}

internal AdministratorController( IUnitOfWork uow )
{
    _uow = uow;
}

您还需要修改MVC项目的AssemblyInfo文件,以使内部构造函数对单元测试项目可见。查找InternalsVisibleToAttribute。

现在在单元测试中,您可以创建假/模拟对象并注入它。您没有指出您正在使用的模拟框架。我们使用FakeItEasy,所以它会像:

var uow = A.Fake<IUnitOfWork>();

var controller = new AdministratorController( uow );

A.CallTo( () => uow.SaveChanges() ).MustHaveHappened();

答案 1 :(得分:0)

您应该模拟您的依赖项。在您的存储库的示例AddRecord()中。之后,您应该使用您期望的模型测试返回的模型字段(您必须在单元测试方法中设置)。