单元测试使用 QueryString 的控制器
UnitTesting a controller that used QueryString
我正在尝试使用此测试方法
[TestMethod]
[Description("Checks if the SearchResults Controller is generating any data from the Report")]
public async Task GetAllOldCustomersContainingTerm_FromSearchResultsControllerTest()
{
// Create mock configuration files for every class
DalConfig config = new DalConfig()
{
ConnectionString = "Trusted_Connection=True;database=AdventureWorks2017;Server=localhost\MSSQL2017",
};
// Create mock options, PrintService and logger
var mockOptions = new Mock<IOptions<DalConfig>>();
mockOptions.Setup(op => op.Value).Returns(config);
var searchResultFunctions = new SearchResultFunctions();
var logger = new Logger<SearchResultsController>(new LoggerFactory());
var mockSearchResultServices = new Mock<SearchResultService>().As<ISearchResultService>();
mockSearchResultServices.CallBase = true;
// Terms to test. In MockDatabase, John exist on FirstName and 12345 on PostalCode
var terms = new SearchTerms
{
FirstName = "John",
PostalCode = "123456"
};
mockSearchResultServices.Setup(x => x.GetAllOldCustomersContainingTermAsync(config, terms))
.ReturnsAsync(new WebApiMockDatabaseRecordsProvider().GetAllMockOldCustomersDtos());
// Create mock controller
var testController = new SearchResultsController(logger, mockSearchResultServices.Object, searchResultFunctions, mockOptions.Object);
var result = await testController.GetAllOldCustomersContainingTermAsync() as OkObjectResult;
// Check if data is being returned from the Controller
Assert.IsTrue(result.Value != null);
测试以下控制器。
在我使用 QueryString 之前,我有一个带参数的 HttpGet 并且测试成功:
[ApiController]
[Route("[controller]")]
public class SearchResultsController : ControllerBase
{
readonly ILogger<SearchResultsController> _logger;
ISearchResultService ResultService;
ISearchResultFunctions ResultFunctions;
DalConfig DalConfig;
public SearchResultsController(ILogger<SearchResultsController> logger
, ISearchResultService resultService, ISearchResultFunctions resultFunctions, IOptions<DalConfig> settings)
{
DalConfig = settings.Value;
ResultService = resultService;
ResultFunctions = resultFunctions;
_logger = logger;
}
/// <summary>
/// Returns all customers with values that matches in any of the terms
/// Searches all the customer fields except BusinessEntityId and BirthDate
/// </summary>
/// <param name="terms">a list of string terms, seperated by space</param>
/// <returns></returns>
[HttpGet("FindOldCustomers/{terms?}")]
public async Task<IActionResult> GetAllOldCustomersContainingTermAsync()
{
//if (terms == null)
var terms = new SearchTerms()
{
FirstName = Request.Query["FirstName"],
LastName = Request.Query["LastName"],
EmailAddress = Request.Query["EmailAddress"],
Gender = Request.Query["Gender"],
AddressLine1 = Request.Query["AddressLine1"],
AddressLine2 = Request.Query["AddressLine2"],
City = Request.Query["City"],
JobTitle = Request.Query["JobTitle"],
PhoneNumber = Request.Query["PhoneNumber"],
PostalCode = Request.Query["PostalCode"],
};
var config = new DalConfig()
{
ConnectionString = DalConfig.ConnectionString,
};
var task = await ResultService.GetAllOldCustomersContainingTermAsync(config, terms);
if (task.Count == 0)
return NotFound();
return Ok(ResultFunctions.ConvertToJSON(task));
}
我收到空引用异常,我不确定为什么。
我也不确定我是否必须以某种方式将条款对象传递给控制器。使用参数,我正在传递参数中的术语。
我在控制器中添加了一个检查请求是否为空并且现在测试通过
我认为 null 检查(如您的回答中所建议的)在这里不是正确的方法。虽然我通常不会反对这一点,但 Request 对象在生产环境中不可能为空。事实上,通过添加 null 检查,您允许测试分支,这样它就不会真正测试生产中使用的方法的功能。
真正的解决方案是模拟 Request,以便您可以提供 Controller 方法所需的查询字符串参数。有关这方面的一些建议,请参阅 this answer。
我正在尝试使用此测试方法
[TestMethod]
[Description("Checks if the SearchResults Controller is generating any data from the Report")]
public async Task GetAllOldCustomersContainingTerm_FromSearchResultsControllerTest()
{
// Create mock configuration files for every class
DalConfig config = new DalConfig()
{
ConnectionString = "Trusted_Connection=True;database=AdventureWorks2017;Server=localhost\MSSQL2017",
};
// Create mock options, PrintService and logger
var mockOptions = new Mock<IOptions<DalConfig>>();
mockOptions.Setup(op => op.Value).Returns(config);
var searchResultFunctions = new SearchResultFunctions();
var logger = new Logger<SearchResultsController>(new LoggerFactory());
var mockSearchResultServices = new Mock<SearchResultService>().As<ISearchResultService>();
mockSearchResultServices.CallBase = true;
// Terms to test. In MockDatabase, John exist on FirstName and 12345 on PostalCode
var terms = new SearchTerms
{
FirstName = "John",
PostalCode = "123456"
};
mockSearchResultServices.Setup(x => x.GetAllOldCustomersContainingTermAsync(config, terms))
.ReturnsAsync(new WebApiMockDatabaseRecordsProvider().GetAllMockOldCustomersDtos());
// Create mock controller
var testController = new SearchResultsController(logger, mockSearchResultServices.Object, searchResultFunctions, mockOptions.Object);
var result = await testController.GetAllOldCustomersContainingTermAsync() as OkObjectResult;
// Check if data is being returned from the Controller
Assert.IsTrue(result.Value != null);
测试以下控制器。 在我使用 QueryString 之前,我有一个带参数的 HttpGet 并且测试成功:
[ApiController]
[Route("[controller]")]
public class SearchResultsController : ControllerBase
{
readonly ILogger<SearchResultsController> _logger;
ISearchResultService ResultService;
ISearchResultFunctions ResultFunctions;
DalConfig DalConfig;
public SearchResultsController(ILogger<SearchResultsController> logger
, ISearchResultService resultService, ISearchResultFunctions resultFunctions, IOptions<DalConfig> settings)
{
DalConfig = settings.Value;
ResultService = resultService;
ResultFunctions = resultFunctions;
_logger = logger;
}
/// <summary>
/// Returns all customers with values that matches in any of the terms
/// Searches all the customer fields except BusinessEntityId and BirthDate
/// </summary>
/// <param name="terms">a list of string terms, seperated by space</param>
/// <returns></returns>
[HttpGet("FindOldCustomers/{terms?}")]
public async Task<IActionResult> GetAllOldCustomersContainingTermAsync()
{
//if (terms == null)
var terms = new SearchTerms()
{
FirstName = Request.Query["FirstName"],
LastName = Request.Query["LastName"],
EmailAddress = Request.Query["EmailAddress"],
Gender = Request.Query["Gender"],
AddressLine1 = Request.Query["AddressLine1"],
AddressLine2 = Request.Query["AddressLine2"],
City = Request.Query["City"],
JobTitle = Request.Query["JobTitle"],
PhoneNumber = Request.Query["PhoneNumber"],
PostalCode = Request.Query["PostalCode"],
};
var config = new DalConfig()
{
ConnectionString = DalConfig.ConnectionString,
};
var task = await ResultService.GetAllOldCustomersContainingTermAsync(config, terms);
if (task.Count == 0)
return NotFound();
return Ok(ResultFunctions.ConvertToJSON(task));
}
我收到空引用异常,我不确定为什么。 我也不确定我是否必须以某种方式将条款对象传递给控制器。使用参数,我正在传递参数中的术语。
我在控制器中添加了一个检查请求是否为空并且现在测试通过
我认为 null 检查(如您的回答中所建议的)在这里不是正确的方法。虽然我通常不会反对这一点,但 Request 对象在生产环境中不可能为空。事实上,通过添加 null 检查,您允许测试分支,这样它就不会真正测试生产中使用的方法的功能。
真正的解决方案是模拟 Request,以便您可以提供 Controller 方法所需的查询字符串参数。有关这方面的一些建议,请参阅 this answer。