Need help calling a Repository from a Controller in Unit Testing - c#

I am needing to set up a Unit Test for our project. In our Controllers we are using a Unit of Work which holds all the repositories and calling the repository in our IHttpActionResult to get the data.
So far I have set up a Mock of the Interfaces and this is calling the correct IHttpActionResult in the Controller but there is no data coming back.
[TestMethod]
public void TestMethod1()
{
var unitOfWork = new Mock<IUnitOfWork>();
var repo = new Mock<IAuditReleaseRepository>();
unitOfWork.Setup(e => e.AuditReleaseRepository).Returns(repo.Object);
var auditReleaseController = new AuditReleaseController(unitOfWork.Object);
var result = auditReleaseController.Get() as ViewResult;
var model = result.ViewData.Model as IQueryable<AuditReleas>;
Assert.AreEqual(12, model.Count());
}
public class AuditReleaseController : BaseController
{
private IAuditReleaseRepository _auditReleaseRepository;
private IUnitOfWork _unitOfWork;
public AuditReleaseController(IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
this._auditReleaseRepository = unitOfWork.AuditReleaseRepository;
}
[HttpGet, Route("audit-releases")]
public IHttpActionResult Get()
{
var query = this._auditReleaseRepository.GetAll();
return Ok(query);
}
}
public class AuditReleaseRepository : RepositoryBase<AuditReleas>, IAuditReleaseRepository
{
private readonly RetailAssignmentEntities _entities;
public AuditReleaseRepository(RetailAssignmentEntities entities) : base(entities)
{
this._entities = entities;
}
IEnumerable<AuditReleaseDto> IDtoRepository<AuditReleaseDto>.GetAll()
{
return base.GetAll().Where(x=>x.IsReleaseEnabled).Select(AuditReleaseMapping.All).OrderByDescending(x => x.Id);
}
}
This is the Mapping that is taking place to get the data in the GetAll method:
public class AuditReleaseMapping
{
public static Expression<Func<AuditReleas, AuditReleaseDto>> All = (auditRelease) => new AuditReleaseDto()
{
EndDate = auditRelease.AuditReleaseEndDate,
Id = auditRelease.AuditReleaseId,
Name = auditRelease.AuditReleaseName,
StartDate = auditRelease.AuditReleaseStartDate,
AuditPeriodId = auditRelease.AuditPeriod.AuditPeriodId,
AuditYearId = auditRelease.AuditPeriod.AuditYear.AuditYearId,
AuditEndDate = auditRelease.AuditPeriod.AuditEndDate,
AuditStartDate = auditRelease.AuditPeriod.AuditStartDate
};
}
What would be ideal is to call the Controller, which would call the repository, which would then call the Mapping but so far it's not even calling the Repository to get the data. I need help getting that functionality set up.

It looks like you need to Setup the behavior for your Mock repo.GetAll(). You will need to create a list of AuditReleaseDto's for your Mocked repo to return. Call it TestAuditReleaseDtos. You can create this TestData in the beginning of your TestMethod or in the TesstClass initialization. Then use it in a line right after creating your Mock:
var repo = new Mock<IAuditReleaseRepository>();
repo.Setup(r => r.GetAll()).Returns(TestAuditReleaseDtos);
unitOfWork.Setup(e => e.AuditReleaseRepository).Returns(repo.Object);

Related

Mock Repository With Expected Object Using ReturnsAsync Returns Null

I'm creating a random object that I'm expecting back from the test, and using the ReturnsAsync method when setting up the mock repo. The controller inside the Unit Test is returning null, however.
The main difference between my code and a lot of the others is that I'm using AutoMapper to return the DTO object in my controller as an OK object. I'm not sure if that's causing my issue.
Controller Instantiation
private readonly ISuperHeroRepo _repo;
public IMapper _mapper { get; }
public SuperHeroController(ISuperHeroRepo repo, IMapper mapper)
{
_repo = repo;
_mapper = mapper;
}
Repo Method
public async Task<SuperHero> GetSuperHero(int id)
{
return await _db.SuperHeros.FindAsync(id);
}
Mapper Profile
public class SuperHeroProfiles : Profile
{
public SuperHeroProfiles()
{
//Source -> Target
CreateMap<SuperHero, SuperHeroReadDTO>()
.ForMember(target => target.LegalName, option => option.MapFrom(source => $"{source.LegalFirstName} {source.LegalLastName}"))
.ForMember(target => target.Jurisdiction, option => option.MapFrom(source => $"{source.JurisdictionCity}, {source.JurisdictionState}"));
CreateMap<SuperHero, SuperHeroDTO>();
}
}
Controller Method
[HttpGet("{id}")]
public async Task<ActionResult<SuperHeroReadDTO>> Get(int id)
{
var hero = await _repo.GetSuperHero(id);
if (hero == null)
{
return NotFound("Hero Not Found");
}
else
{
// This is where it might be breaking
return Ok(_mapper.Map<SuperHeroReadDTO>(hero));
}
}
Unit Test
// Instantiated
readonly Mock<ISuperHeroRepo> repoMock = new();
readonly Mock<IMapper> mapperMock = new();
private readonly Random random = new();
........
[Fact]
public async Task Get_WithExistingHero_ReturnsExpectedSuperHero()
{
// Arrange
SuperHero expected = CreateRandomSuperHero();
repoMock.Setup(repo => repo.GetSuperHero(It.IsAny<int>()))
.ReturnsAsync(expected);
var controller = new SuperHeroController(repoMock.Object, mapperMock.Object);
// Act - This returns null. Debugging in the controller, I get the object back from repo
var result = await controller.Get(random.Next());
// Assert
Assert.IsType<SuperHeroReadDTO>(result.Value);
var dto = result.Value;
Assert.Equal(expected.SuperHeroName, dto.SuperHeroName);
Assert.Equal($"{expected.LegalFirstName} {expected.LegalLastName}", dto.LegalName);
Assert.Equal($"{expected.JurisdictionCity}, {expected.JurisdictionState}", dto.Jurisdiction);
}
Edited: Added the controller instantiation, and the Mapper Profile. Not sure if it'll add more info.
#shree.pat18 was indeed correct. I did end up needing to set up the Mapper object in the Unit Test and passing it back into the controller. I'll need to refactor, but here below is what resolved it:
[Fact]
public async Task Get_WithExistingHero_ReturnsExpectedSuperHero()
{
// Arrange
SuperHero expected = CreateRandomSuperHero();
repoMock.Setup(repo => repo.GetSuperHero(It.IsAny<int>()))
.ReturnsAsync(expected);
// Setup of the mock Mapper
var mockMapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new SuperHeroProfiles());
});
var mapper = mockMapper.CreateMapper();
var controller = new SuperHeroController(repoMock.Object, mapper);
// Act
var result = await controller.Get(random.Next());
// Assert
Assert.IsType<SuperHeroReadDTO>(result.Value);
var dto = result.Value;
Assert.Equal(expected.SuperHeroName, dto.SuperHeroName);
Assert.Equal($"{expected.LegalFirstName} {expected.LegalLastName}", dto.LegalName);
Assert.Equal($"{expected.JurisdictionCity}, {expected.JurisdictionState}", dto.Jurisdiction);
}

Asp.Net MVC 5 Testing IoC + Dependency Injection

I'm trying to test my project. I have never used tests before and I am starting to learn I would like a help, in the simplest case I want test this public ActionResult Index() but I don't know how to Inject those dependencies.
Controller:
Controller:
public class WorkPlacesController : Controller
{
private readonly IWorkPlaceService workPlaceService;
public WorkPlacesController(IWorkPlaceService workPlaceService)
{
this.workPlaceService = workPlaceService;
}
// GET: WorkPlaces
public ActionResult Index()
{
var workPlaces = workPlaceService.GetWorkPlaces(includedRelated:
true);
return View(workPlaces);
}
}
Here is my Service
Service
public class WorkPlaceService : IWorkPlaceService
{
private readonly IWorkPlaceRepository workPlacesRepository;
private readonly IUnitOfWork unitOfWork;
public WorkPlaceService(IWorkPlaceRepository workPlacesRepository, IUnitOfWork unitOfWork)
{
this.workPlacesRepository = workPlacesRepository;
this.unitOfWork = unitOfWork;
}
}
public interface IWorkPlaceService
{
IEnumerable<WorkPlace> GetWorkPlaces(string workPlaceDescription = null, bool includedRelated = true);
}
And my Repository
Repository
public class WorkPlaceRepository : RepositoryBase<WorkPlace>, IWorkPlaceRepository
{
public WorkPlaceRepository(IDbFactory dbFactory)
: base(dbFactory) { }
public WorkPlace GetWorkPlaceByDescription(string workPlaceDescription)
{
var workPlace = this.DbContext.WorkPlaces.Where(c => c.Description == workPlaceDescription).FirstOrDefault();
return workPlace;
}
}
public interface IWorkPlaceRepository : IRepository<WorkPlace>
{
WorkPlace GetWorkPlaceByDescription(string workPlaceDescription);
}
Factory
public class DbFactory : Disposable, IDbFactory
{
AgendaEntities dbContext;
public AgendaEntities Init()
{
return dbContext ?? (dbContext = new AgendaEntities());
}
protected override void DisposeCore()
{
if (dbContext != null)
dbContext.Dispose();
}
}
I tried to do something like this:
public void BasicIndexTest()
{
// Arrange
var mockRepository = new Mock<IWorkPlaceService>();
var controller = new WorkPlacesController(mockRepository.Object);
// Act
ActionResult actionResult = controller.Index() as ViewResult;
// Assert
Assert.IsInstanceOfType(actionResult, typeof(List<WorkPlace>));
}
How do I inject in this controller the data needed to go in the database and bring the results?
I Want test this public ActionResult Index() but I don't know how to Inject those dependencies.
Mock the behavior of required dependencies of the controller for the test and assert the desired behavior when the test is exercised.
For example, based on what you have done so far
public void BasicIndexTest() {
// Arrange
var mockService = new Mock<IWorkPlaceService>();
var workPlaces = new List<WorkPlace>() {
new WorkPlace()
};
mockService
.Setup(_ => _.GetWorkPlaces(It.IsAny<string>(), It.IsAny<bool>()))
.Returns(workPlaces);
var controller = new WorkPlacesController(mockService.Object);
// Act
var actionResult = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(actionResult);
var model = actionResult.Model;
Assert.IsNotNull(model)
Assert.IsInstanceOfType(model, typeof(List<WorkPlace>));
Assert.AreEqual(workPlaces, model);
}
Only the IWorkPlaceService was needed for the testing of Index action, but fake data was needed for the invocation of the GetWorkPlaces method. So the mock was configured to return a list of objects when called and pass it to the view result.

C# mocking generic repository using Moq

I have implemented generic repository in my project. Now I am writing test cases for my consumer. I am trying to mock database function through Moq but I am getting values from database rather than the one I faked through Moq. Below I am sharing my implementation. Hoping someone will help me in pointing out the mistake I made.
My interface:
public interface IEventsRepository<T> : IRepository<T> {
T GetEventsByEventId(int eventId); }
My class:
public class EventsTableRepository : EFDBRepository<EventsModel>, IEventsRepository<EventsModel> {
public EventsModel GetEventsByEventId(int eventId)
{
return _dbSet.Where(x => x.EventID == eventId).FirstOrDefault();
}
}
My Consumer:
public static Response<string> EventsAccept(EventsAlertsRequest logMsgId)
{
IEventsRepository<EventsModel> eventsRepo = (IEventsRepository<EventsModel>)RepositoryLocator.GetRepositoryObject(STMEnums.RepositoryName.EventsTableRepository.ToString());
EventsModel eventmodel = new EventsModel();
eventmodel = eventsRepo.GetEventsByEventId(eachlogMsgId);
return EventStatusChangeResponse;
}
Test Method:
public void EventsAcceptSuccessTest()
{
EventsModel eventmodel = new EventsModel();
eventmodel.Message = "TEST";
Mock<IEventsRepository<EventsModel>> obj = new Mock<IEventsRepository<EventsModel>>();
obj.Setup(m => m.GetEventsByEventId(Moq.It.IsAny<int>())).Returns(eventmodel);
EventStatusChangeResponse = Diagnostics_.EventsAccept(logMsgId);
Assert.AreEqual(eventmodel.Status, EventStatus.ACCEPTED);
}
No where in the provided example is the mock being injected into the subject under test. Also it looks like the subject method under test is using static Service Locator anti-pattern to get the desired model. Making an assumption here as the rest of the class is not shown in relation to that variable.
The locator would need to have been an injected abstraction to allow an opportunity to mock its expected behavior
public class Consumer {
private IRepositoryLocator RepositoryLocator;
public Consumer(IRepositoryLocator RepositoryLocator) {
this.RepositoryLocator = RepositoryLocator;
}
public Response<string> EventsAccept(EventsAlertsRequest logMsgId) {
IEventsRepository<EventsModel> eventsRepo = (IEventsRepository<EventsModel>)RepositoryLocator.GetRepositoryObject(STMEnums.RepositoryName.EventsTableRepository.ToString());
EventsModel eventmodel = new EventsModel();
eventmodel = eventsRepo.GetEventsByEventId(eachlogMsgId);
return EventStatusChangeResponse;
}
}
This would then mean that the locator would also have to be mocked properly for the test to be exercised to completion.
public void EventsAcceptSuccessTest() {
//Arrange
var eventmodel = new EventsModel() {
Message = "TEST"
};
var repositoryMock = new Mock<IEventsRepository<EventsModel>>();
repositoryMock
.Setup(_ => _.GetEventsByEventId(It.IsAny<int>()))
.Callback((int id) => {
eventmodel.EventID = id;
eventmodel.Status = EventStatus.ACCEPTED;
})
.Returns(eventmodel);
var locatorMock = new Mock<IRepositoryLocator>();
locatorMock.Setup(_ => _.GetRepositoryObject(It.IsAny<string>())).Returns(repositoryMock.Object);
var subject = new Consumer(locatorMock.Object);
//Act
var response = subject.EventsAccept(logMsgId);
//Assert
Assert.AreEqual(eventmodel.Status, EventStatus.ACCEPTED);
}

How to mock Automapper (IMapper) in controller

I am trying to write a unit test for my existing MVC Web Aplication. In that I am facing some problem in automapper (IMapper) Whenever am using map function it returns null value.
My Controller Code:
public class UserAdministrationController : BaseController
{
private readonly iUserService _userService;
private readonly IMapper _mapper;
public NewsController(iUserService userService, IMapper mapper)
{
_userService = userService;
_mapper = mapper;
}
public ActionResult Create(int CompanyID == 0)
{
UserDetail data = _userService(CompanyID);
var Modeldata = _mapper.Map<UserDetailViewModel, UserDetail>(data);
return View(Modeldata);
}
}
Mock Mapping Code:
public class MappingDataTest : CommonTestData
{
public Mock<IMapper> MappingData()
{
var mappingService = new Mock<IMapper>();
UserDetailViewModel interview = getUserDetailViewModel(); // get value of UserDetailViewModel
UserDetail im = getUserDetail(); // get value of UserDetails
mappingService.Setup(m => m.Map<UserDetail, UserDetailViewModel>(im)).Returns(interview);
mappingService.Setup(m => m.Map<UserDetailViewModel, UserDetail>(interview)).Returns(im);
return mappingService;
}
}
Mocking Code:
[TestClass]
public class UserAdminControllerTest
{
private MappingDataTest _common;
[TestInitialize]
public void TestCommonData()
{
_common = new MappingDataTest();
}
[TestMethod]
public void UserCreate()
{
//Arrange
UserAdministrationController controller = new UserAdministrationController(_common.mockUserService().Object, _common.MappingData().Object);
controller.ControllerContext = _common.GetUserIdentity(controller);
// Act
ViewResult newResult = controller.Create() as ViewResult;
// Assert
Assert.IsNotNull(newResult);
}
}
Mapper is not working its always showing the null value in controller. kindly help me. Thanks in Advance.
I would recommend not mocking AutoMapper. There's not much value in controller unit tests for one, and this is similar to mocking a JSON serializer. Just use the real thing.
You should try the following:
public class MappingDataTest : CommonTestData
{
public Mock<IMapper> MappingData()
{
var mappingService = new Mock<IMapper>();
UserDetail im = getUserDetail(); // get value of UserDetails
mappingService.Setup(m => m.Map<UserDetail, UserDetailViewModel>(It.IsAny<UserDetail>())).Returns(interview); // mapping data
mappingService.Setup(m => m.Map<UserDetailViewModel, UserDetail>(It.IsAny<UserDetailtViewModel>())).Returns(im); // mapping data
return mappingService;
}
}
The thing is, your mock was expecting the exact instance of UserDetailViewModel interview = getUserDetailViewModel(); to setup this mapping, and this is why it was returning null. Null it will be expecting any reference to UserDetailViewModel and for any reference to UserDetailtViewModel it will return the expected mapped instance.

How do you unit test a MVC controller with EF SaveChanges

Below is a controller with a Post Method. How do i write a unit-test against the CREATE method without saving the changes to the database?
I am trying to write test against my controllers so that when other developers change the code it will not break my functionality ( i have a little bit of functionality on the Create method to keep it simple for now).
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.) my UOW looks something like this:
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) And my AdministratorRepository constructor looks like:
private readonly MasterContext _context;
public AdministratorRepository(MasterContext context)
{
_context = context;
}
You need to be able to inject a fake/mock IUnitOfWork into your controller. The simplest way to do that is to create an internal constructor on the controller that takes the fake object and create a property that either creates a new instance or returns the existing one.
private IUnitOfWork _uow;
private IUnitOfWork UnitOfWork
{
get
{
_uow = _uow ?? new UnitOfWork();
return _uow;
}
}
public AdministratorController() {}
internal AdministratorController( IUnitOfWork uow )
{
_uow = uow;
}
You'll also need to modify the AssemblyInfo file for the MVC project to make the internal constructor visible to the unit test project. Look up the InternalsVisibleToAttribute for that.
Now in the unit test you can create your fake/mock object and inject it. You don't indicate what mocking framework you're using. We use FakeItEasy, so it would be something like:
var uow = A.Fake<IUnitOfWork>();
var controller = new AdministratorController( uow );
A.CallTo( () => uow.SaveChanges() ).MustHaveHappened();
You should mock your dependencies.In your example AddRecord() of your repository.And after that you should test the returning model fields with your expected model(that you have to set in your unit testing method).

Categories