Question

I am working my way through the Contoso sample for some TDD practice and my tests for retrieving students are passing.

My test for creating a new student fails (although the actual code works) as I believe the DBContext is not being mocked.

What should I refactor in order to get this test to past?

The test fails as so:

Contoso.Tests.Controllers.StudentControllerTest.Create_HttpPost_Should_Save_New_Student: Expected: 9 But was: 8

Heres the concrete 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);
    }
}

The StudentController

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);
    }

...
}

Here's where I mock the 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;
    }

Here's the failing test

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);
    }
Was it helpful?

Solution

It looks like the Add method for StudentRepository needs to be mocked as well. I'm not if sure if the syntax is right, but try the following:

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top