Testing the action method to implement GetQuestions

Follow these steps to implement a couple of tests on the GetQuestions method:

  1. We'll start by creating a new class called QuestionsControllerTests in the Tests project with the following content:
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Xunit;
using Moq;
using QandA.Controllers;
using QandA.Data;
using QandA.Data.Models;

namespace BackendTests
{
public class QuestionsControllerTests
{

}
}
  1. We are going to verify that calling GetQuestions with no parameters returns all the questions. Let's create the test method for this and 10 mock questions:
[Fact]
public async void
GetQuestions_WhenNoParameters_ReturnsAllQuestions()
{
var mockQuestions = new List<QuestionGetManyResponse>();
for (int i = 1; i <= 10; i++)
{
mockQuestions.Add(new QuestionGetManyResponse
{
QuestionId = 1,
Title = $"Test title {i}",
Content = $"Test content {i}",
UserName = "User1",
Answers = new List<AnswerGetResponse>()
});
}
}

Notice that the method is flagged as asynchronous with the async keyword because the action method we are testing is asynchronous.

  1. Let's create a mock data repository definition using Moq:
[Fact]
public async void
GetQuestions_WhenNoParameters_ReturnsAllQuestions()
{
...
var mockDataRepository = new Mock<IDataRepository>();
mockDataRepository
.Setup(repo => repo.GetQuestions())
.Returns(() => Task.FromResult(mockQuestions.AsEnumerable()));
}

We create a mock object from the IDataRepository interface using the Mock class from Moq. Now, we can use the Setup and Returns methods on the mock object to define that the GetQuestions method should return our mock questions. The method we are testing is asynchronous, so we need to wrap the mock questions with Task.FromResult in the mock result.

  1. We need to mock the configuration object that reads appsettings.json. This is what the controller depends on:
[Fact]
public async void
GetQuestions_WhenNoParameters_ReturnsAllQuestions()
{
...
var mockConfigurationRoot = new Mock<IConfigurationRoot>();
mockConfigurationRoot.SetupGet(config =>
config[It.IsAny<string>()]).Returns("some setting");
}

 The preceding code will return any string when appsettings.json is read, which is fine for our test.

  1. Next, we need to create an instance of the controller by passing in an instance of the mock data repository and mock configuration settings:
[Fact]
public async void
GetQuestions_WhenNoParameters_ReturnsAllQuestions()
{
...
var questionsController = new QuestionsController(
mockDataRepository.Object, null,
null, null, mockConfigurationRoot.Object);
}

The Object property on the mock data repository definition gives us an instance of the mock data repository to use.

Notice that we can pass in null for cache, SignalR hub, HTTP client factory, and configuration dependencies. This is because they are not used in the action method implementation we are testing. 

  1. Now, we can call the action method we are testing:
[Fact]
public void async
GetQuestions_WhenNoParameters_ReturnsAllQuestions()
{
...
var result = await questionsController.GetQuestions(null, false);
}

We pass null in as the search parameter and false as the includeAnswers parameter. The other parameters are optional, so we don't pass these in.

  1. Now, we can check the result is as expected:
[Fact]
public void async
GetQuestions_WhenNoParameters_ReturnsAllQuestions()
{
...

Assert.Equal(10, result.Count());
mockDataRepository.Verify(
mock => mock.GetQuestions(), Times.Once());

}

We have checked that 10 items are returned.

We have also checked that the GetQuestions method in the data repository is called once. 

  1. Let's give this a try by right-clicking the test in Test Explorer and selecting Run Selected Tests:

The test passes, as we expected.

  1. Now, we are going to create a second test to verify that calling GetQuestions with a search parameter calls the GetQuestionsBySearchWithPaging method in the data repository:
[Fact]
public async void
GetQuestions_WhenHaveSearchParameter_ReturnsCorrectQuestions()
{
var mockQuestions = new List<QuestionGetManyResponse>();
mockQuestions.Add(new QuestionGetManyResponse
{
QuestionId = 1,
Title = "Test",
Content = "Test content",
UserName = "User1",
Answers = new List<AnswerGetResponse>()
});

var mockDataRepository = new Mock<IDataRepository>();
mockDataRepository
.Setup(repo =>
repo.GetQuestionsBySearchWithPaging("Test", 1, 20))
.Returns(() =>
Task.FromResult(mockQuestions.AsEnumerable()));

var mockConfigurationRoot = new Mock<IConfigurationRoot>();
mockConfigurationRoot.SetupGet(config =>
config[It.IsAny<string>()]).Returns("some setting");

var questionsController = new QuestionsController(
mockDataRepository.Object, null,
null, null, mockConfigurationRoot.Object);

var result =
await questionsController.GetQuestions("Test", false);

Assert.Single(result);
mockDataRepository.Verify(mock =>
mock.GetQuestionsBySearchWithPaging("Test", 1, 20),
Times.Once());
}

This follows the same pattern as the previous test, but this time we're mocking the GetQuestionsBySearchWithPaging method in the data repository and checking that this is called. If we run the test, it will pass as expected.

That completes the tests on the GetQuestions method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.137.169