unit-testing - 使用 Moq 和 EF 4.1 模拟 UnitOfWork

标签 unit-testing asp.net-mvc-3 moq unit-of-work

我正在通过 Contoso 示例进行一些 TDD 练习,并且我的检索学生测试通过了。

我创建新学生的测试失败了(尽管实际代码有效),因为我相信 DBContext 没有被模拟。

为了通过这个测试,我应该重构什么?

测试失败:

Contoso.Tests.Controllers.StudentControllerTest.Create_HttpPost_Should_Save_New_Student: 预期:9 但是是:8

这是具体的 UnitOfWork

public class UnitOfWork : IUnitOfWork
{
    private SchoolContext context = new SchoolContext();

    private IStudentsRepository studentsRepository;

    private bool disposed = false;

    public IStudentsRepository StudentsRepository
    {
        get
        {
            if (this.studentsRepository == null)
            {
                this.studentsRepository = new StudentsRepository(context);
            }
            return studentsRepository;
        }
    }


    public void Save()
    {
        context.SaveChanges();
    }


    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

学生 Controller

public class StudentController : Controller
{
    private IUnitOfWork _unitOfWork;

    public StudentController(IUnitOfWork unitOfWork)
    {
        this._unitOfWork = unitOfWork;
    }

...

    [HttpPost]
    public ActionResult Create(Student student)
    {
        if (ModelState.IsValid)
        {
            _unitOfWork.StudentsRepository.Add(student);
            _unitOfWork.StudentsRepository.Save();

            return RedirectToAction("Details", new { id = student.StudentID });
        }

        return View(student);
    }

...
}

这是我模拟 IUnitOfWork 的地方

    public static IUnitOfWork MockUnitOfWork(List<Student> students)
    {
        var mockUnitOfWork = new Mock<IUnitOfWork>();

        mockUnitOfWork.Setup(x => x.StudentsRepository.Students()).Returns(students.AsQueryable());

        return mockUnitOfWork.Object;
    }

这是失败的测试

private IUnitOfWork unitOfWork = UnitTestHelpers.MockUnitOfWork(testData);
...



    [Test]
    public void Create_HttpPost_Should_Save_New_Student()
    {
        // Arrange
        var studentsCount = unitOfWork.StudentsRepository.Students().Count();
        var controller = new StudentController(unitOfWork);
        var student = Fakes.FakeStudentsData.CreateStudent();

        // Act
        var result = controller.Create(student);

        // Assert
        Assert.AreEqual(studentsCount+1, unitOfWork.StudentsRepository.Students().Count());
        Assert.IsInstanceOf(typeof(RedirectToRouteResult), result);
    }

最佳答案

看起来 StudentRepository 的 Add 方法也需要被模拟。我不确定语法是否正确,但请尝试以下操作:

public static IUnitOfWork MockUnitOfWork(List<Student> students)
{
    var mockUnitOfWork = new Mock<IUnitOfWork>();

    mockUnitOfWork.Setup(x => x.StudentsRepository.Students()).Returns(students.AsQueryable());
    mockUnitOfWork.Setup(x => x.StudentsRepository.Add(It.IsAny<Student>())).Callback<Student>((s) => students.Add(s));

    return mockUnitOfWork.Object;
}

关于unit-testing - 使用 Moq 和 EF 4.1 模拟 UnitOfWork,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6809902/

相关文章:

unit-testing - 将单元测试用例的 Private 方法更改为 Public 是一个很好的做法

c# - 使用最小起订量模拟 Linq `Any` 谓词

.net - 如何模拟 System.Data.Linq.Table<MyClass>

javascript - 预期的 spy 不会被内部函数调用

javascript - 模拟 firebase 模块后模拟 firebase auth 方法的实现

perl - 设计一个perl Moose类方便测试

asp.net-mvc-3 - ASP MVC 3,如何在 Controller 中设置模型属性?

javascript - 引用错误 : can't find variable x when using grunt test in yeoman

c# - 无法使用类型为“System.Data.Entity.Core.Objects.ObjectQuery”的实例进行调用

asp.net-mvc-3 - 无法将 [] 索引应用于 ICollection 类型的表达式