0

I will like to write a xunit test for the controller method below

        [HttpGet]
        [Route("GetPosts")]
        public async Task<IActionResult> GetPosts()
        {
            try
            {
                var posts = await postRepository.GetPosts();
                if (posts == null)
                {
                    return NotFound();
                }

                return Ok(posts);
            }
            catch (Exception)
            {
                return BadRequest();
            }
        }

My viewmodel looks like this.

        public class PostViewModel
            {
                public int PostId { get; set; }
                public string Title { get; set; }
                public string Description { get; set; }
                public int? CategoryId { get; set; }
                public DateTime? CreatedDate { get; set; }
                public string CategoryName { get; set; }
            }

Here is what my repository looks like.

        public async Task<List<PostViewModel>> GetPosts()
                {
                    if (db != null)
                    {
                        return await (from p in db.Post
                                      from c in db.Category
                                      where p.CategoryId == c.Id
                                      select new PostViewModel
                                      {
                                          PostId = p.PostId,
                                          Title = p.Title,
                                          Description = p.Description,
                                          CategoryId = p.CategoryId,
                                          CategoryName = c.Name,
                                          CreatedDate = p.CreatedDate
                                      }).ToListAsync();
                    }

                    return null;
        }

I started getting this error message

        cannot convert from 'System.Collections.Generic.List<CoreServices.ViewModel.PostViewModel>' 
        to 'System.Threading.Tasks.Task<System.Collections.Generic.List<CoreServices.ViewModel.PostViewModel>>' 

Here is what my xunit test looks like.

        public class PostControllerTest
        {
            private readonly Mock<IPostRepository> _mockRepo;
            private readonly PostController  _controller;

            public PostControllerTest()
            {
                _mockRepo = new Mock<IPostRepository>();
                _controller = new PostController(_mockRepo.Object);
            }

            [Fact]
            public void GetPosts_TaskExecutes_ReturnsExactNumberOfPosts()
            {
                _mockRepo.Setup(repo => repo.GetPosts())
                    .Returns(new List<PostViewModel>() { new PostViewModel(), new PostViewModel() });

                    //var result = 
                    //Assert.True()
            }
        }

I will like to complete my first test which will show the count of the post is 2 (mocking a dependency). How can I write this/complete this test ?

Baba
  • 2,059
  • 8
  • 48
  • 81
  • 1
    Does this answer your question? [Setting up a C# Test with Moq against Async methods](https://stackoverflow.com/questions/50117170/setting-up-a-c-sharp-test-with-moq-against-async-methods) – devNull Dec 28 '19 at 02:21

2 Answers2

0

I think everything else is fine except your Returns value setup. You need to return a Task. Try this

_mockRepo.Setup(repo => repo.GetPosts())
                    .Returns(Task.FromResult(new List<PostViewModel>() { new PostViewModel(), new PostViewModel() }));

adeel41
  • 3,123
  • 1
  • 29
  • 25
  • Thanks a lot. Seems to be working. The error message is gone. How can I complete this test with assert ? – Baba Dec 28 '19 at 02:36
  • You can call _mockRepo.VerifyAll() which will verify that the mocked methods were executed at least once. There are other options available such as verifying that a method was only mocked once, etc. – djsoteric Dec 28 '19 at 02:39
  • you can assert that controller returns Ok result since you mocked to return 2 PostViewModel. And same for when there are no posts then you are returning a NotFound result. – adeel41 Dec 28 '19 at 02:41
  • Thanks and i get that but the purpose of the test is to do a count and return a count of two posts. How do I write that in the test method above? – Baba Dec 28 '19 at 02:42
  • In my opinion, you don't need that test because you will always return same number of posts which you have mocked to return. So what is the point then? You need to write tests for the controller which is using that dependency. and not the dependency which you have mocked to return whatever you want – adeel41 Dec 28 '19 at 02:45
  • i did the _mockRepo.VerifyAll() and got this error. The test did not build. Message: System.IO.FileNotFoundException : Could not load file or assembly 'Microsoft.AspNetCore.Mvc.Core, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified. – Baba Dec 28 '19 at 02:48
0

Try using ReturnsAsync instead of Returns. GetPosts is an asynchronous method.

djsoteric
  • 188
  • 1
  • 10