Hamid Mosalla Hamid Mosalla - 1 year ago 68
C# Question

Stubed Unit of Work method with Moq doesn't return the expected integer

I have a project created using Asp.Net Core, but I have a problem with unit testing one part of my controller's action, I use xUnit.net(2.2.0-beta2-build3300) for testing and Moq(4.6.25-alpha) for mocking, and FluentAssertions(4.13.0) and GenFu(1.1.1) to help me with my tests, I have a Unit of Work class (note that I cut it down to what's relevant to my question):

public class UnitOfWork : IUnitOfWork

private readonly WebForDbContext _context;

public UnitOfWork(WebForDbContext context)
_context = context;

private IContactRepository _contactRepository;

public IContactRepository ContactRepository

if (this._contactRepository == null)
this._contactRepository = new ContactRepository(_context);
return _contactRepository;

In my ContactRepository I have:

public class ContactRepository:IContactRepository
private WebForDbContext _context;

public ContactRepository(WebForDbContext context)
_context = context;

public Task<int> AddNewContactAsync(Contact contact)
return _context.SaveChangesAsync();

I inject the Unit of Work to my controller, my action:

public async Task<IActionResult> Create(ContactViewModel contactViewModel)
var contactWioutJavascript = _webForMapper.ContactViewModelToContact(contactViewModel);

int addContactResultWioutJavascript = await _uw.ContactRepository.AddNewContactAsync(contactWioutJavascript);

if (addContactResultWioutJavascript > 0)
return View("Success");

What I want to do is to stub my
method to return an integer bigger than 0 (10 in this case), to inter the if clause, and test to see if the correct view is returned, my test class:

public class ContactControllerTests

private Mock<IUnitOfWork> _uw;
private Mock<IWebForMapper> _webForMapper;

public ContactControllerTests()
_uw = new Mock<IUnitOfWork>();

_webForMapper = new Mock<IWebForMapper>();

public async Task Create_SouldReturnSuccessView_IfNewContactAdded()
var contactViewModel = A.New<ContactViewModel>();

_webForMapper.Setup(s => s.ContactViewModelToContact(contactViewModel)).Returns(A.New<Contact>());

_uw.Setup(u => u.ContactRepository.AddNewContactAsync(A.New<Contact>())).ReturnsAsync(10);

var sut = new ContactController(_uw.Object, _webForMapper.Object);

var result = (ViewResult)await sut.Create(contactViewModel);


But the method
returns 0, and my test doesn't enter the if condition that leads to
return View("Success")
, I know that the problem doesn't have to do with
because I've used it with other async methods and it works, also
is stubbed correctly and map the view model to my domain model and
is populated with value, but when I debug the test and reach the
line, it returns 0, no matter what I do.

The things I did, but didn't work:

I mocked the ContactRepository, and tried to stub that instead:

_contactRepository.Setup(c => c.AddNewContactAsync(A.New<Contact>())).ReturnsAsync(10);

_uw.SetupGet<IContactRepository>(u => u.ContactRepository).Returns(_contactRepository.Object);

I also found other questions:

Moq Unit of Work

how to moq simple add function that uses Unit of Work and Repository Pattern

Mocking UnitOfWork with Moq and EF 4.1

But none of them helped, I'd appreciate any help.

Answer Source

You are almost there. Two things:

  1. You do need to setup the ContactRepository property as Moq doesn't support "chaining" of setups.

  2. Also, you need to use It.IsAny<>() instead of A.New<>:

    _contactRepository.Setup(c => c.AddNewContactAsync(It.IsAny<Contact>())).ReturnsAsync(10);

    This says "match any Contact that is passed in". When you used A.New<>(), you were saying "match the Contact instance that I just created with A.New<>(). In effect, that will never match anything since you didn't save or use the return value of A.New<>().