i'm new to unit testing and Moq. I wrote 4 tests who all throw the same exception and i think i need to add these parameters CombatHelperContext, IMapper when mocking the CharacterRepository but how do i do that?
My goal is to test crud functionality, views and more.
public class CharacterTests
{
[Fact]
public async Task GetAll_ReturnsAViewResult_WithAListOfCharacters()
{
// Arrange
var mockRepo = new Mock<CharacterRepository>();
mockRepo.Setup(repo => repo.GetAll())
.Returns(GetTestCharacters());
var controller = new CharacterController(mockRepo.Object);
// Act
var result = await controller.Get();
// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<List<CharacterDto>>(
viewResult.ViewData.Model);
Assert.Equal(4, model.Count());
}
[Fact]
public async Task Delete_Character()
{
// Arrange
var mockRepo = new Mock<CharacterRepository>();
mockRepo.Setup(repo => repo.Delete(1));
var controller = new CharacterController(mockRepo.Object);
var characters = GetTestCharacters();
// Act
var result = await controller.Get();
// Assert
Assert.Null(characters.Where(c => c.Id == 1));
}
[Fact]
public async Task Post_NewCharacter_ReturnsInViewResult()
{
// Arrange
CharacterDto newCharacterDto = new CharacterDto();
newCharacterDto.Id = 5;
var mockRepo = new Mock<CharacterRepository>();
mockRepo.Setup(repo => repo.Add(newCharacterDto));
var controller = new CharacterController(mockRepo.Object);
var characters = GetTestCharacters();
// Act
var result = await controller.Get();
// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<List<CharacterDto>>(
viewResult.ViewData.Model);
Assert.Equal(5, model.Count());
}
[Fact]
public async Task Update_Character()
{
// Arrange
var mockRepo = new Mock<CharacterRepository>();
var characters = GetTestCharacters();
CharacterDto characterToUpdate = characters.FirstOrDefault(c => c.Name == "Zero Two");
var controller = new CharacterController(mockRepo.Object);
// Act
var result = await controller.Get();
characterToUpdate.Name = "Zero Three";
mockRepo.Setup(repo => repo.Update(characterToUpdate));
// Assert
Assert.NotNull(characters.FirstOrDefault(c => c.Name == "Zero Three"));
}
private IQueryable<CharacterDto> GetTestCharacters()
{
var characters = new List<CharacterDto>();
characters.Add(new CharacterDto()
{
Id = 1,
Name = "Zero Two"
});
characters.Add(
new CharacterDto
{
Id = 2,
Name = "Ander"
});
characters.Add(
new CharacterDto
{
Id = 3,
Name = "Jingles"
});
characters.Add(new CharacterDto
{
Id = 4,
Name = "Arthas Menethil"
});
var queryableCharacters = characters.AsQueryable();
return queryableCharacters;
}
}
This the Repository i'm mocking
public class CharacterRepository : MappingRepository<Character, CharacterDto>
{
public CharacterRepository(CombatHelperContext combatHelperContext, IMapper mapper) : base(combatHelperContext, mapper)
{
}
}
Depend on abstraction rather than implementation - create repository interface:
public interface ICharacterRepository
{
IEnumerable<Character> GetAll();
void Delete(int id);
void Add(Character character);
}
Now mocking works like a charm:
var mockRepo = new Mock<ICharacterRepository>();
Also consider using something like AutoFixture or NBuilder to generate test objects.
[Fact]
public async Task GetAll_Returns_ViewResult_With_List_Of_Characters()
{
// Arrange
var fixture = new Fixture();
var characters = fixture.CreateMany<Character>();
var mockRepo = new Mock<ICharacterRepository>();
mockRepo.Setup(repo => repo.GetAll()).Returns(characters);
var controller = new CharacterController(mockRepo.Object);
// Act
var result = await controller.Get();
// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<List<CharacterDto>>(viewResult.ViewData.Model);
Assert.Equal(characters.Count(), model.Count());
}
If you cannot change current implementation and depend on interface, then you should provide constructor arguments as params list to new mock:
var combatHelperContext = new CombatHelperContext();
var mapperMock = new Mock<IMapper>();
var mockRepo = new Mock<CharacterRepository>(combatHelperContext, mapperMock.Object);
Related
I am writing unit tests and this mapper is causing me grief again. I understood from a previous post that I cannot Mock the mapper, i have to use it straight away. So I have created maps but it says missing type map configuration.
public RoleDto GetSingle([FromRoute] string id)
{
var r = roleManagerWrapper.GetSingleRole(id);
return mapper.Map<RoleDto>(r);
}
It breaks when it tries to map the object. Is there any special mapping for Task <IdentityRole> that needs to be implemented?
public async Task<IdentityRole> GetSingleRole(string roleId)
{
var role = await this.roleManager.Roles.SingleOrDefaultAsync(r => r.Id == roleId);
return role;
}
Here is my test that only counts the number of roles that are created.
[Test]
public async Task Get_Single()
{
TestSetup();
var roleManagerWrapperMock = new Mock<IRoleManagerWrapper>();
var adminRole = new IdentityRole()
{
Name = "Admin",
Id = "4a8de423-5663-4831-ac07-7ce92465b008"
};
var managerRole = new IdentityRole()
{
Name = "Manager",
Id = "40f74162-3359-4253-9b5a-ad795b328267"
};
ApplicationDbContext.Roles.Add(managerRole);
ApplicationDbContext.Roles.Add(adminRole);
ApplicationDbContext.SaveChanges();
var sut = new RolesController(roleManagerWrapperMock.Object, ApplicationDbContext, Mapper);
var result = sut.GetSingle("4a8de423-5663-4831-ac07-7ce92465b008");
Assert.AreEqual(result.UserCount, 1);
}
protected void TestSetup(string databaseName = null)
{
if (databaseName == null)
{
databaseName = GetTestName();
}
TestCleanup();
ServiceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
dbContextOptions = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName)
.UseInternalServiceProvider(ServiceProvider)
.Options;
ApplicationDbContext = new ApplicationDbContext(dbContextOptions);
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<RoleDto, IdentityRole>();
cfg.CreateMap<IdentityRole, RoleDto>();
cfg.CreateMap<CreateRoleDto, IdentityRole>().ReverseMap();
cfg.CreateMap<UpdateRoleDto, IdentityRole>().ReverseMap();
});
Mapper = config.CreateMapper();
}
The action needs to be refactored to use proper asyn syntax since GetSingleRole returns Task<IdentityRole>
public Task<RoleDto> GetSingle([FromRoute] string id) {
IdentityRole r = await roleManagerWrapper.GetSingleRole(id);
return mapper.Map<RoleDto>(r);
}
And the test updated accordingly
[Test]
public async Task Get_Single() {
//Arrange
TestSetup();
var roleManagerWrapperMock = new Mock<IRoleManagerWrapper>();
//...omitted for brevity
var sut = new RolesController(roleManagerWrapperMock.Object, ApplicationDbContext, Mapper);
//Act
RoleDto result = await sut.GetSingle("4a8de423-5663-4831-ac07-7ce92465b008");
//Assert
Assert.AreEqual(result.UserCount, 1);
}
I am trying to unit test a c# controller method. I have looked up many questions and nothing quite gives me instructions on how to unit test the API controller. The code that is correct is below for the method. How do you unit test for the brackets.
I have figured out how to test the method "Reverse Payment", but I am using moq and xunit to test the actual c# method. This is my current unit test:
public class PaymentsControllerTests : BackOfficeIntegrationTestBase
{
private readonly CurrentDateProvider _currentDateProvider;
[BackOfficeRolesAuthorize(BackOfficeUserRole.Admin, BackOfficeUserRole.CSR, BackOfficeUserRole.DealerSupportRep,
BackOfficeUserRole.CSRManager)]
[Fact]
public async Task AdminReversalPermissions()
{
IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());
var mediator = fixture.Freeze<Mock<IMediator>>();
var currentDateProvider = fixture.Freeze<CurrentDateProvider>();
var mockRepo = new Mock<IMediator>();
var controller = new PaymentsController(mockRepo.Object);
// Setup Dependencies
//DataContext dataContext = SetUpDatabase(fixture);
ReversePaymentSetup(fixture, mediator);
var result = await controller.ReversePayment(LeaseInfo.ApplicationId, 100);
var viewResult = result as NoContentResult;
Assert.NotNull(viewResult);
}
private void ReversePaymentSetup(IFixture fixture, Mock<IMediator> mediator)
{
PaymentData data = new PaymentData();
//Mock the mediator
var paymentPlan = new Data.Model.PaymentPlan()
{
LeaseId = 1,
LeaseTerm = LeaseTerm.Year,
DefermentDays = 5,
FirstPaymentDate = DateTime.ParseExact("01/01/2019", "d", CultureInfo.InvariantCulture),
StoreState = "VA"
};
var responseData = new BuildPaymentPlanResponse();
responseData.Data = new BuildPaymentPlanResponse.InitializePaymentPlanResponseData()
{
PaymentPlan = paymentPlan
};
PaymentStatusChangeManualRequest request = fixture.Build<PaymentStatusChangeManualRequest>()
.With(x => x.PaymentPlanId, LeaseInfo.ApplicationId)
.With(x => x.PaymentId, 100)
.With(x => x.Status, PaymentStatus.Reversed)
.Create();
Assert.Equal(PaymentStatus.Reversed, request.Status);
Assert.Equal(100, request.PaymentId);
Assert.NotNull(LeaseInfo.ApplicationId);
}
}
}
[ProducesResponseType(typeof(ErrorResponse), (int)HttpStatusCode.NotFound)]
[HttpPut("{paymentId}/ReversePayment")]
[BackOfficeRolesAuthorize(BackOfficeUserRole.Admin, BackOfficeUserRole.CSR, BackOfficeUserRole.DealerSupportRep,
BackOfficeUserRole.CSRManager)]
public async Task<IActionResult> ReversePayment(int paymentPlanId, int paymentId)
{
await _mediator.Send(new PaymentStatusChangeManualRequest
{
PaymentPlanId = paymentPlanId,
PaymentId = paymentId,
Status = PaymentStatus.Reversed
});
return NoContent();
}
I want to test GetMoviesAsync of my Controller. I don't know where I am doing wrong in my Moq setup. I am getting 0 item from GetMoviesAsync.
What am I doing wrong?
// Api-Controller:
public interface ICommand
{
Task<IEnumerable<Movie>> GetMoviesAsync();
}
public class SampleController : ControllerBase
{
private readonly ICommand movieCommand;
public SampleController(ICommand command)
{
movieCommand = command;
}
[HttpGet]
public async Task<IActionResult> GetMoviesAsync()
{
var movies = await movieCommand.GetMoviesAsync();
return Ok(movies);
}
}
// Unit-Test:
public class SampleControllerTest
{
private IEnumerable<Movie> MovieList()
{
IList<Movie> movies = new List<Movie>()
{
new Movie()
{
ID =1,
Title = "Test",
ReleaseDate = DateTime.Now,
RunningTimeInMinutes = 100
}
};
return movies;
}
private SampleController GetSampleController()
{
var command = new Mock<ICommand>();
return new SampleController(command.Object);
}
[Fact]
public async Task GetMovies_Test()
{
// Arrange
var controller = GetSampleController();
var commadMock = new Mock<ICommand>();
// How to setup moq here?
commadMock.Setup(s => s.GetMoviesAsync()).Returns(Task.FromResult<IEnumerable<Movie>>(MovieList())).Verifiable();
// Act
var response = await controller.GetMoviesAsync() as OkObjectResult;
// Problem is here,
var li=response.Value as IEnumerable<Movie>;
}
}
What am I doing wrong?
Two completely different mocks are being used.
One is used to create the controller
private SampleController GetSampleController()
{
var command = new Mock<ICommand>();
return new SampleController(command.Object);
}
and another is being created and setup in the test.
var controller = GetSampleController();
var commadMock = new Mock<ICommand>();
// How to setup moq here?
commadMock.Setup(s => s.GetMoviesAsync()).Returns(Task.FromResult<IEnumerable<Movie>>(MovieList())).Verifiable();
To solve this, use the same mock to get the desired behavior
[Fact]
public async Task GetMovies_Test() {
// Arrange
var commadMock = new Mock<ICommand>();
var controller = new SampleController(commadMock.Object); //<---
commadMock
.Setup(_ => _.GetMoviesAsync())
.ReturnsAsync(MovieList())
.Verifiable();
// Act
var response = await controller.GetMoviesAsync() as OkObjectResult;
//Assert
var list = response.Value as IEnumerable<Movie>;
//...
}
Note the use of ReturnsAsync to setup the returned Task
It seems that you are not using the correct mock on the Controller. The one that you are using does not have any setup on top of the method GetMoviesAsync
For me helped almost the solution offered by Nkosi but with little difference
[Fact]
public async Task GetMovies_Test() {
// Arrange
var commadMock = new Mock<ICommand>();
var controller = new SampleController(commadMock.Object); //<---
commadMock
.Setup(_ => _.GetMoviesAsync())
.ReturnsAsync(MovieList());
// Act
var response = await controller.GetMoviesAsync();
//Assert
var returnValue = Assert.IsType<ViewResult>(response);
var model = returnValue.Model as IEnumerable<Movie>;
//...
}
I am trying to test a controller in my asp.netcore application. The test is failing because of auto-mapper.
I tried to mock to the auto-mapper but i do not know how to use it correctly.
Would anyone be able to suggest a way of overcoming this?
Thanks.
BooksController.cs
[HttpGet("{id:int}")]
public IActionResult GetBook(int id)
{
var bookfromRepo = _repository.GetBook(id);
var book = Mapper.Map<BookDto>(bookfromRepo);
return Ok(book);
}
startup.cs
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<Data.Database.Entities.Book, BookDto>();
});
ControllerTest.cs
[Fact(DisplayName = "GetBook")]
public void GetBook()
{
//act
var fakerepository = new Mock<IBPDRepository>();
var sut = new BooksController(fakerepository.Object);
//act
var book = new BookDto();
var viewModelBook = new BookDto {
Id = 1,
Name = "C#",
Review = "good",
Pages = "500",
Rating = "8",
Price ="$10.00"
};
//var mockMapper = new Mock //stuck here;
sut.GetBook(1);
//assert
IActionResult actionResult = sut.GetBook(2);
Assert.Equal("C#",viewModelBook.Name);
}
Change your Mapper to an IMapper, and then you can write something like that for the UnitTest :
(I'm doing that free-hand, so there might be slight adjustments to make)
[Fact(DisplayName = "GetBook")]
public void GetBook()
{
// Arrange
var mockBook1 = new Mock<BookDto>(Behavior = MockBehavior.Strict);
var mockBook2 = new Mock<BookDto>(Behavior = MockBehavior.Strict);
var mockRepository = new Mock<IBPDRepository>(Behavior = MockBehavior.Strict);
mockRepository.Setup(r => r.GetBook(It.Is<int>(1)).Returns(mockBook1.Object)
var mockMapper = new Mock<IAutoMapper>(Behavior = MockBehavior.Strict);
mockMapper.Setup(m => m.Map<BookDto>(mockBook1.Object)).Returns(mockBook2.Object);
// You might have to change the constructor.
var sut = new BooksController(mockRepository.Object, mockMapper.Object);
IActionResult actionResult;
// Act
actionResult = sut.GetBook(1);
var actualBook = actionResult.Model as BookDto;
// Assert
Assert.Equal(mockBook2.Object, actualBook);
}
The reason why I'd use mockBook rather than straight BookDto is that this way, combined with the Strict behavior, you know the method didn't change anything on it since you did no setup on it.
In ViewComponent object, HttpContext and User are read-only properties.
How to unit test such a component?
I'm using the MSTest Freamwork.
The follow properties are used in my code
Cookie
Session
User(System.Security.Principal)
public ViewViewComponentResult Invoke()
{
var vm = new SummaryViewModel();
if (User.Identity is ClaimsIdentity identity && identity.IsAuthenticated)
{
vm.IsAuthenticated = true;
vm.UserName = identity.Claims.FirstOrDefault(c => c.Type == "UserName").Value;
vm.PhotoUrl = identity.Claims.FirstOrDefault(c => c.Type == "FacePicture").Value;
}
return View(vm);
}
[TestMethod]
public void UserSummaryVcTest()
{
var component = new UserSummaryViewComponent();
var model = component.Invoke().ViewData.Model as SummaryViewModel;
Assert.AreEqual("UserName", model.UserName);
}
According to source code the ViewComponent relies on the ViewComponentContext.ViewContext to expose those read only properties, Which in turn accesses the HttpContext. That is your entry point to mock the desired values.
[TestMethod]
public void UserSummaryVcTest() {
// Arrange
var expected = "Username value";
var httpContext = new DefaultHttpContext(); //You can also Mock this
//...then set user and other required properties on the httpContext as needed
var viewContext = new ViewContext();
viewContext.HttpContext = httpContext;
var viewComponentContext = new ViewComponentContext();
viewComponentContext.ViewContext = viewContext;
var viewComponent = new UserSummaryViewComponent();
viewComponent.ViewComponentContext = viewComponentContext;
//Act
var model = viewComponent.Invoke().ViewData.Model as SummaryViewModel;
//Assert
Assert.AreEqual(expected, model.UserName);
}
Here is just a samle for async,
[TestMethod]
public async System.Threading.Tasks.Task InvokeAsyncNameAsync()
{
# setup mocks
...
var httpContext = new DefaultHttpContext();
var viewContext = new ViewContext();
viewContext.HttpContext = httpContext;
var viewComponentContext = new ViewComponentContext();
viewComponentContext.ViewContext = viewContext;
var footerComponent = CreateComponentInstance();
footerComponent.ViewComponentContext = viewComponentContext;
ViewViewComponentResult result = await footerComponent.InvokeAsync() as ViewViewComponentResult;
FooterModel resultModel = (FooterModel)result.ViewData.Model;
....
# do your asserts verifications
Assert.AreEqual(expectedTest, resultModel.FooterText);
}