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();
}
Related
I am having an issue with my moq when I try to return data, of serviceResponse but it's not coming
I tried to write unit test in Xunit for service layer
My controller
[HttpGet]
public async Task<IActionResult> GetHospitals(
[FromQuery] HospitalRequestFilter hospitalRequestFilter,
[FromServices] IOptions<ApiBehaviorOptions> options)
{
var serviceResponse = await this._hospitalService.GetHospitalsAsync(hospitalRequestFilter, true);
return OkResponse<HospitalQueryModel>(serviceResponse, true);
}
My controller's unit test
public async Task GetHospitals_WithOutFilter_ReturnsAllData()
{
//Arrange
MockServiceFactory mockServiceFactory = new MockServiceFactory();
var hospitalServiceMock = mockServiceFactory.GetHospitals();
var loggerMoq = new Mock<ILogger<HospitalsController>>();
ILogger<HospitalsController> logger = loggerMoq.Object;
ApiBehaviorOptions apiBeaviorOptions = new ApiBehaviorOptions() { };
var mock = new Mock<IOptions<ApiBehaviorOptions>>();
mock.Setup(ap => ap.Value).Returns(apiBeaviorOptions);
var hospitalValidation = mockServiceFactory.GetHospitalValidation();
HospitalsController HospitalController = new HospitalsController(logger,hospitalServiceMock,hospitalValidation);
//Act
var filter = new HospitalRequestFilter() { Code="Abc",Name="Abc hospital"};
var hospital = await HospitalController.GetHospitals(filter,mock.Object);
//Assert
Assert.NotNull(hospital);
}
My controller for the delete method :
[HttpDelete("{toDoListId}")]
public async Task<ActionResult> DeleteToDoList(int toDoListId)
{
var toDoListEntity = await _toDoListRepository.GetSpecificTodoAsync(toDoListId);
if (toDoListEntity == null)
{
return NotFound();
}
_toDoListRepository.DeleteToDoList(toDoListEntity);
await _toDoListRepository.SaveChangesAsync();
return NoContent();
}
My repository :
public async Task<ToDoList?> GetSpecificTodoAsync(int taskId)
{
return await _context.ToDoLists.Where(c => c.Id == taskId).FirstOrDefaultAsync();
}
public void DeleteToDoList(ToDoList toDoListDto)
{
_context.ToDoLists.Remove(toDoListDto);
}
My testcase for checking if the item got deleted and if it returns no content after being deleted. But both of my test cases are failing. Any help on how to write test cases for the delete part, I would be really grateful. I am also trying to test other methods but I am unfortunately stuck here. Please kindly help me
public class UnitTest1
{
private readonly Mock<IToDoListRepository> repositoryStub = new ();
private readonly Mock<IMapper> mapper = new Mock<IMapper>();
private readonly Random Rand = new();
private ToDoList GenerateRandomItem()
{
return new()
{
Id = Rand.Next(),
Description= Guid.NewGuid().ToString(),
Title = Guid.NewGuid().ToString(),
StartDate = DateTime.Now,
EndDate = DateTime.Now,
Done = false
};
}
[Fact]
public void Delete_removesEntry()
{
//arrange
var existingItem = GenerateRandomItem();
var controller = new ToDoController(repositoryStub.Object, mapper.Object);
var itemID = existingItem.Id;
//act
controller.DeleteToDoList(itemID);
//assert
Assert.Null(repositoryStub.Object.GetSpecificTodoAsync(itemID));
}
[Fact]
public async Task DeleteItemAsync_WithExistingItem_ReturnNoContent()
{
//Arrange
var existingItem = GenerateRandomItem();
repositoryStub.Setup(repo => repo.GetSpecificTodoAsync(existingItem.Id)).ReturnsAsync((existingItem));
var itemID = existingItem.Id;
var controller = new ToDoController(repositoryStub.Object, mapper.Object);
//Act
var result = await controller.DeleteToDoList(itemID);
//assert
result.Should().BeOfType<NoContentResult>();
}
Both test cases are failing because the mock has not been setup to behave as expected for each test case.
There is also a potential race condition in the shown tests since they are sharing the same mock instance. This will cause issues when setting up the mock as one test case could potentially override the setup of another case.
Update the tests so that they are isolated from each other.
In the first test, the expected behavior can be verified by checking the mock to see if the expected member was invoked.
[Fact]
public async Task DeleteToDoList_Should_RemoveEntry() {
//arrange
ToDoList existingItem = GenerateRandomItem();
var itemID = existingItem.Id;
Mock<IToDoListRepository> repositoryStub = new ();
//Setup expected behavior of mock
repositoryStub
.Setup(_ => _.GetSpecificTodoAsync(itemID))
.ReturnsAsync(existingItem);
var controller = new ToDoController(repositoryStub.Object, mapper.Object);
//act
await controller.DeleteToDoList(itemID);
//assert
repositoryStub.Verify(_ => _.DeleteToDoList(existingItem));
}
In the other test, the mock needs be setup to make sure the subject executes to completion.
[Fact]
public async Task DeleteToDoList_WithExistingItem_Should_ReturnNoContent() {
//Arrange
ToDoList existingItem = GenerateRandomItem();
var itemID = existingItem.Id;
Mock<IToDoListRepository> repositoryStub = new ();
//Setup expected behavior of mock
repositoryStub
.Setup(_ => _.GetSpecificTodoAsync(itemID))
.ReturnsAsync(existingItem);
repositoryStub.Setup(_ => _.SaveChangesAsync()).ReturnsAsynt(true);
var controller = new ToDoController(repositoryStub.Object, mapper.Object);
//Act
ActionResult result = await controller.DeleteToDoList(itemID);
//assert
result.Should().BeOfType<NoContentResult>();
}
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);
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.