How to test async Task<IActionResult> returning IEnumerable<model> using moq in xunit?
Asked Answered
H

3

5

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>;
         }
    }
Halflife answered 2/1, 2019 at 13:48 Comment(0)
M
6

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

Malacca answered 2/1, 2019 at 14:10 Comment(0)
C
0

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

Colonial answered 2/1, 2019 at 15:26 Comment(0)
J
0

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>;

    //...
 }
Jared answered 20/7, 2022 at 22:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.