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
{
get
{
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)
{
_context.Contacts.Add(contact);
return _context.SaveChangesAsync();
}
}
I inject the Unit of Work to my controller, my action:
[HttpPost]
[ValidateAntiForgeryToken]
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 AddNewContactAsync
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>();
}
[Fact]
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);
result.ViewName.Should().Be("Success");
}
}
But the method AddNewContactAsync
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 ReturnAsync
because I've used it with other async methods and it works, also _webForMapper
is stubbed correctly and map the view model to my domain model and contactWioutJavascript
is populated with value, but when I debug the test and reach the addContactResultWioutJavascript
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:
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.