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>();
}
Related
I have this class called Handler, which is a MassTransit IConsumer:
public class Handler : IConsumer<ICommand>
{
private readonly IOrderRepository _orderRepository;
public Handler(IOrderRepository orderRepository)
{
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
}
public async Task Consume(ConsumeContext<ICommand> context)
{
var command = context.Message;
var orderId = new OrderId(command.OrderId);
var order = await _orderRepository.FindOrderAsync(orderId, context.CancellationToken);
if (order is null)
{
await context.RespondAsync(CommandResponse.NotFound);
return;
}
order.Cancel();
await _orderRepository.SaveOrderAsync(order, context.CancellationToken);
await context.RespondAsync(CommandResponse.Submitted);
}
}
I have two unit tests for it. Here's the one that seems to work fine:
[TestMethod]
public async Task Consume_WithExistingOrderId_CancelsOrderAndSavesChangesAndReturnsSubmitted()
{
// Arrange
var mockConsumer = new Mock<IConsumer<ICommand>>();
var mockRepository = new Mock<IOrderRepository>();
var sut = new Handler(mockRepository.Object);
var mockCommand = new Mock<ICommand>();
var mockContext = new Mock<ConsumeContext<ICommand>>();
mockContext.Setup(x => x.Message).Returns(mockCommand.Object);
mockContext.Setup(x => x.RespondAsync(It.IsAny<CommandResponse>())).Returns(Task.CompletedTask);
var existingOrderId = new OrderId(Guid.NewGuid());
mockCommand.Setup(x => x.OrderId).Returns(existingOrderId.Value);
var order = GetTestOrder(existingOrderId);
mockRepository.Setup(x => x.FindOrderAsync(existingOrderId, It.IsAny<CancellationToken>())).ReturnsAsync(order);
// Act
await sut.Consume(mockContext.Object);
// Assert
mockRepository.Verify(x => x.SaveOrderAsync(order, It.IsAny<CancellationToken>()), Times.Once());
mockContext.Verify(x => x.RespondAsync(CommandResponse.Submitted), Times.Once());
order.IsCancelled.Should().BeTrue();
}
And here's the one that isn't doing what I expected:
[TestMethod()]
public async Task Consume_WithNonExistantOrderId_ReturnsNotFoundResponseAndDoesNotSave()
{
// Arrange
var mockRepository = new Mock<IOrderRepository>();
var sut = new Handler(mockRepository.Object);
var mockCommand = new Mock<ICommand>();
var mockContext = new Mock<ConsumeContext<ICommand>>();
mockContext.Setup(x => x.Message).Returns(mockCommand.Object);
mockContext.Setup(x => x.RespondAsync(It.IsAny<CommandResponse>())).Returns(Task.CompletedTask);
var nonExistantOrderId = new OrderId(Guid.NewGuid());
mockCommand.Setup(x => x.OrderId).Returns(nonExistantOrderId.Value);
mockRepository.Setup(x => x.FindOrderAsync(nonExistantOrderId, It.IsAny<CancellationToken>())).ReturnsAsync((Order?)null);
// Act
await sut.Consume(mockContext.Object);
// Assert
mockRepository.Verify(x => x.SaveOrderAsync(It.IsAny<Order>(), It.IsAny<CancellationToken>()), Times.Never());
mockContext.Verify(x => x.RespondAsync(CommandResponse.NotFound), Times.Once());
}
Both unit tests require that the Handler calls the RespondAsync method of the MassTransit context exactly once. However, the second unit test doesn't pass, saying that the method was never called. I don't see why it was never called. When I debug into the method it appears to show the method is called.
I can't tell if my test is wrong or if my system under test is wrong. Can anybody see the problem please?
(Also, if anybody can see how to make my code more testable and my unit tests shorter and simpler that would also be appreciated.)
The problem is with the nonExistantOrderId and using that for the match in expectation.
mockRepository
.Setup(x => x.FindOrderAsync(nonExistantOrderId, It.IsAny<CancellationToken>()))
.ReturnsAsync((Order?)null);
the mock expects to get that specific instance when the subject is being exercised but the subject initialized its own instance which causes the mock to not invoke the async call and exit the subject before that target line can be invoked.
This is why
mockRepository.Verify(x => x.SaveOrderAsync(It.IsAny<Order>(), It.IsAny<CancellationToken>()), Times.Never());
supposedly passed verification, and
mockContext.Verify(x => x.RespondAsync(CommandResponse.NotFound), Times.Once());
failed since the subject code exited before reaching both members that are the targets of your verification.
Loosen the match using It.IsAny<OrderId>()
mockRepository
.Setup(x => x.FindOrderAsync(It.IsAny<OrderId>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((Order?)null);
so that the mocked async call can be invoked and allow the code to flow to completion.
I have accepted Nkosi's answer because it solved the problem stated in the question. Thank you, Nkosi.
However, the resources that were provided by the MassTransit boss-man, #Chris Patterson, were helpful in making a better unit test altogether. That's why I'm posting this alternative answer. This answer rewrites the original unit test to use the MassTransit test harness, and I hope it helps somebody one day.
Chris's links have somehow disappeared from sight. However, I think he posted this:
https://www.youtube.com/watch?v=Cx-Mc0DCpfE&t=545s
And this:
https://masstransit-project.com/usage/testing.html
The rewritten method:
public interface ICommand
{
Guid OrderId { get; }
}
public record Command : ICommand
{
public Command(Guid orderId)
{
OrderId = orderId;
}
public Guid OrderId { get; }
}
public class Handler : IConsumer<ICommand>
{
private readonly IOrderRepository _orderRepository;
public Handler(IOrderRepository orderRepository)
{
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
}
public async Task Consume(ConsumeContext<ICommand> context)
{
var command = context.Message;
OrderId orderId = new OrderId(command.OrderId);
var order = await _orderRepository.FindOrderAsync(orderId, context.CancellationToken);
if (order is null)
{
await context.RespondAsync(CommandResponse.NotFound);
return;
}
order.Cancel();
await _orderRepository.SaveOrderAsync(order, context.CancellationToken);
await context.RespondAsync(CommandResponse.Submitted);
}
}
The rewritten unit test class:
[TestClass()]
public class Handler_Tests
{
private static OrderId ExistingOrderId = new OrderId("d94108e4-1121-401a-a6ef-c7736054041d");
private static OrderId NonExistentOrderId = new OrderId("daaa72a0-8f8c-4a9b-b4ad-ebefbb6b5aa2");
private static CustomerId ExistingCustomerId = new CustomerId("5fbf40d8-c064-4821-8948-a520863e6242");
[TestMethod()]
public async Task Consume_WithExistingOrderId_CancelsOrderAndSavesChangesAndReturnsSubmitted2()
{
// Arrange
var harness = new InMemoryTestHarness();
var mockRepository = GetMockOrderRepository();
var sut = harness.Consumer(() =>
{
return new Handler(mockRepository.Object);
});
await harness.Start();
try
{
var requestClient = await harness.ConnectRequestClient<ICommand>();
var command = new Command(ExistingOrderId.Value);
// Act
var response = await requestClient.GetResponse<CommandResponse>(command, It.IsAny<CancellationToken>());
// Assert
mockRepository.Verify(x => x.SaveOrderAsync(It.IsAny<Order>(), It.IsAny<CancellationToken>()), Times.Once());
response.Message.Result.Should().Be(CommandResponse.Results.Submitted);
}
finally
{
await harness.Stop();
}
}
[TestMethod()]
public async Task Consume_WithNonExistentOrderId_ReturnsNotFoundResponseAndDoesNotSave()
{
// Arrange
var harness = new InMemoryTestHarness();
var mockRepository = GetMockOrderRepository();
var sut = harness.Consumer(() =>
{
return new Handler(mockRepository.Object);
});
await harness.Start();
try
{
var requestClient = await harness.ConnectRequestClient<ICommand>();
var command = new Command(NonExistentOrderId.Value);
var response = await requestClient.GetResponse<CommandResponse>(command, It.IsAny<CancellationToken>());
mockRepository.Verify(x => x.SaveOrderAsync(It.IsAny<Order>(), It.IsAny<CancellationToken>()), Times.Never());
response.Message.Result.Should().Be(CommandResponse.Results.NotFound);
}
finally
{
await harness.Stop();
}
}
private static Order GetTestOrder(OrderId orderId)
{
var orderItem = GetTestOrderItem();
return Order.Place(orderId, ExistingCustomerId, new[] { orderItem });
}
private static OrderItem GetTestOrderItem()
{
var productId = new ProductId(Guid.NewGuid());
var price = new Price(1, PurchaseCurrency.Usd);
var quantity = new Quantity(1, UnitOfMeasure.Each);
return new OrderItem(productId, quantity, price);
}
private static Mock<IOrderRepository> GetMockOrderRepository()
{
var mockRepository = new Mock<IOrderRepository>();
mockRepository.Setup(x => x.FindOrderAsync(It.IsAny<OrderId>(), It.IsAny<CancellationToken>()))
.ThrowsAsync(new InvalidOperationException(
$"This mock is set up to work with {nameof(ExistingOrderId)} and {nameof(NonExistentOrderId)}."));
mockRepository.Setup(x => x.FindOrderAsync(ExistingOrderId, It.IsAny<CancellationToken>()))
.ReturnsAsync(GetTestOrder(ExistingOrderId));
mockRepository.Setup(x => x.FindOrderAsync(NonExistentOrderId, It.IsAny<CancellationToken>()))
.ReturnsAsync((Order?)null);
return mockRepository;
}
}
I'm trying to write a Unit test case for the delete method of the below controller
public class AssetProxyController : Controller
{
private IRiskAssetProxyService _assetProxyService;
public AssetProxyController( IRiskAssetProxyService assetProxyService)
{
_assetProxyService = assetProxyService;
}
[HttpDelete("{assetId}")]
public ActionResult Delete(string assetId)
{
if (_assetProxyService.DeleteAssetProxyMapping(assetId))
{
return Ok("AssetProxy Deleted");
}
else
{
return BadRequest("Unable to delete AssetProxy");
}
}
}
Test
[TestMethod]
public void Delete_ShouldReturnDeleteAssetProxy()
{
//Mock
var mockContext = new Mock<MainDBContext>();
var faker = AutoFaker.Create();
var assetProxyMappings = faker.Generate<List<AssetProxyMapping>>();
var mockAssetProxyDbSet = GetQueryableMockDbSet<AssetProxyMapping>(assetProxyMappings);
mockContext.Setup(c => c.AssetProxyMapping).Returns(mockAssetProxyDbSet);
//Test
var mocklogger = new Mock<ILogger<RiskDataControllerDbAccess>>();
var positiondbaccess = new Mock<RiskAssetProxyDbAccess>(mockContext,mocklogger);
var mockserviceLogger = new Mock<ILogger<RiskAssetProxyService>>();
var positionService = new Mock<RiskAssetProxyService>(positiondbaccess, mockserviceLogger);
var positionController = new AssetProxyController(positionService.Object);
Assert.AreEqual(true, true);
}
But i keep getting the exception
Test method Risk.DataService.UnitTests.API.AssetProxyControllerTests.Delete_ShouldReturnDeleteAssetProxy threw exception:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException: Can not instantiate proxy of class: Risk.DataServices.RiskAssetProxyService.
Could not find a constructor that would match given arguments:
Moq.Mock`1[Risk.DataServices.RiskAssetProxyDbAccess]
Moq.Mock`1[Microsoft.Extensions.Logging.ILogger`1[Risk.DataServices.RiskAssetProxyService]]
The currently shown test is completely over-engineered based on the shown subject under test.
Given the shown Delete controller action, the test case should be simplified
[TestMethod]
public void AssetProxy_Delete_Should_Return_Ok() {
//Arrange
string assetId = "assetId";
var serviceMock = new Mock<IRiskAssetProxyService>();
serviceMock.Setup(_ => _.DeleteAssetProxyMapping(assetId))
.Returns(true);
AssetProxyController controller = new AssetProxyController(serviceMock.Object);
//Act
ActionResult result = controller.Delete(assetId);
//Assert - using fluent assertions
result.Should().NotBeNull();
string expected = "AssetProxy Deleted";
OkObjectResult okResult = result as OkObjectResult;
okResult.Should().NotBeNull();
string actual = okResult.Value as string;
actual.Should().Be(expected); //same as Assert.AreEqual(expected, actual);
}
Another test case can be done to assert bad requests and would be similar to the case shown above except that the mocked service will be arranged to return false in order to cause the expected behavior and the assertion updated accordingly
I've read similar questions but could not manage to solve my own. I'm using xUnit and I'm running into an issue when one of my methods calls, it's returning null but in fact that I have mocked it.
Interface
public interface IApplicantService
{
Task<Applicant> AddAsync(Applicant applicant);
// other methods
}
Test Case
public class ApplicationControllerTests
{
private readonly Mock<IApplicantService> _mockApplicantService;
private readonly ApplicantController _applicantController;
private readonly IMapper _mockMapper;
public ApplicationControllerTests()
{
_mockApplicantService = new Mock<IApplicantService>();
var mapperConfig = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new ResourceToModelProfile());
cfg.AddProfile(new ModelToResourceProfile());
});
_mockMapper = mapperConfig.CreateMapper();
_applicantController = new ApplicantController(_mockApplicantService.Object, _mockMapper);
}
[Fact]
public async void CreateAsync_WhenApplicantNotExist_ShouldReturn_CreatedAtActionResult_With_Resource()
{
var applicantDto = new ApplicantCreateDto
{
PersonId = 1,
VacancyId = 1
};
_mockApplicantService.Setup(e => e.AddAsync(It.IsAny<Applicant>()))
.Returns(Task.FromResult(new Applicant { Id = 1, PersonId = 1, VacancyId = 1}));
var result = await _applicantController.CreateAsync(applicantDto);
var createdAtActionResult = result as CreatedAtActionResult;
var model = createdAtActionResult.Value as ApplicantResponseDto;
var actual = model.PersonId;
Assert.NotNull(model);
Assert.Equal(1, actual);
Assert.NotNull(createdAtActionResult);
}
}
Controller
[HttpPost]
[Route("CreateAsync")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> CreateAsync([FromBody] ApplicantCreateDto applicantCreateDto)
{
try
{
var applicant = _mapper.Map<ApplicantCreateDto, Applicant>(applicantCreateDto);
var result = await _applicantService.AddAsync(applicant);
// here, result is null, but it was mocked to return an Applicant object
var resource = _mapper.Map<Applicant, ApplicantResponseDto>(result);
return CreatedAtAction(nameof(GetAsync), new { id = result.Id }, resource);
}
catch (ResourceExistException ex)
{
return Conflict(ex.Message);
}
catch(Exception ex)
{
// log exception
return StatusCode(500);
}
}
The mocked method is returning null and I'm getting System.NullReferenceException
This is how your fixed unit test could look like:
[Fact]
public async Task CreateAsync_WhenApplicantNotExist_ShouldReturn_CreatedAtActionResult_With_Resource()
{
//Arrange
var applicantDto = new ApplicantCreateDto { PersonId = 1, VacancyId = 1 };
var applicant = new Applicant { Id = 1, PersonId = 1, VacancyId = 1 };
_mockApplicantService
.Setup(svc => svc.AddAsync(It.IsAny<Applicant>()))
.ReturnsAsync(applicant);
//Act
var result = await _applicantController.CreateAsync(applicantDto);
//Assert
var createdAtActionResult = Assert.IsAssignableFrom<CreatedAtActionResult>(result);
var model = Assert.IsAssignableFrom<ApplicationResponseDto>(createdAtActionResult.Value);
Assert.Equal(1, model.PersonId);
}
I've replaced async void to async Task that way your await will be evaluated properly
I've changed the Returns(Task.FromResult(...)) to ReturnsAsync(...) because this is the recommended way to specify return value in case of async methods
I've also added some comments to separate the different phases of your unit test from each other (Arrange-Act-Assert)
I've changed your assertion logic to use IsAssingableFrom to verify the type itself rather than doing null checks
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>;
//...
}