ASP.NET Тестирование Api-контроллера: Uri (Request.GetEncodedUrl () ...) возвращает ноль - PullRequest
1 голос
/ 29 октября 2019

Я тестирую пост-метод ASP.NET Core Api, но получаю исключение System.NullReferenceException, которое приводит к сбою моего теста.

При попытке вернуть Created () - ActionResult возникает пустое исключение,как это:

return Created(new Uri(Request.GetEncodedUrl() + "/" + personDto.Id), personDto);

Мой personDto.Id, ни personDto не является нулевым, но результат Uri () возвращает нулевое значение. Я гуглил, но не нашел решения, но я считаю, что мне нужно каким-то образом издеваться над методом Uri () (я новичок в тестировании и asp.net в целом). Api хорошо работает при тестировании «живого» на SQL Server.

Я использую Moq и NUnit для тестирования, и ниже приведена часть моих методов установки и тестирования:

public void SetUp()
{
    _mapper = GenerateConcreteInstance();

    _personService = new Mock<IPersonService>();

    _personService.Setup(ps => ps.Create(It.IsAny<Person>())).Verifiable();

    _controller = new PeopleController(_personService.Object, _mapper);
}

[Test]
public void CreatePerson_WhenCalled_IsNotNull()
{
    var personDto = new PersonDto()
    {
        Id = 3,
        Firstname = "Karl",
        Lastname = "Karlsson",
        City = "Oslo",
        Email = "karl.karlsson@test.com"
    };

    var result = _controller.CreatePerson(personDto);

    var createdResult = result as CreatedResult;

    Assert.IsNotNull(createdResult);
}

И мой контроллер, который я пытаюсь проверить:

[HttpPost]
public IActionResult CreatePerson(PersonDto personDto)
{
    if (!ModelState.IsValid)
        return BadRequest();

    var person = _mapper.Map<PersonDto, Person>(personDto);
    person.DateCreated = DateTime.Now;

    _personService.Create(person);
    _personService.Save();

    personDto.Id = person.Id;

    return Created(new Uri(Request.GetEncodedUrl() + "/" + personDto.Id), personDto);
}

Как правильно настроить этот тест, чтобы избежать нулевого исключения? Был бы признателен за любую помощь в решении этой проблемы и указатели в целом, если мой тест не годится для других целей.

Обновление

Я изменилпроверить, как это. Я на правильном пути?

public void CreatePerson_WhenCalled_IsNotNull()
{
    var personDto = new PersonDto()
    {
        Id = 3,
        Firstname = "Karl",
        Lastname = "Karlsson",
        City = "Oslo",
        Email = "karl.karlsson@test.com"
    };

    var request = new Mock<HttpRequest>();
    request.Setup(x => x.Headers).Returns(
        new HeaderDictionary {
        {"X-Requested-With", "XMLHttpRequest"}
    });


    var context = new Mock<HttpContext>();
    context.Setup(x => x.Request).Returns(request.Object);

    _controller.ControllerContext = new ControllerContext()
    {
        HttpContext = context.Object
    };

    var result = _controller.CreatePerson(personDto);

    var createdResult = result as CreatedResult;

    Assert.IsNotNull(createdResult);
}

1 Ответ

0 голосов
/ 30 октября 2019

Request.GetEncodedUrl() расширение полагается на наличие действительного запроса.

/// <summary>
/// Returns the combined components of the request URL in a fully escaped form suitable for use in HTTP headers
/// and other HTTP operations.
/// </summary>
/// <param name="request">The request to assemble the uri pieces from.</param>
/// <returns>The encoded string version of the URL from <paramref name="request"/>.</returns>
public static string GetEncodedUrl(this HttpRequest request)
{
    return BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path, request.QueryString);
}

Источник

, который завершится ошибкой

if (scheme == null)
{
    throw new ArgumentNullException(nameof(scheme));
}

Источник

С показанным примером не связано ни контекста, ни запроса, поэтому я предлагаю предоставить действительный контекст с необходимыми элементами, заполненными для выполнения теста, как ожидалось.

//...omitted for brevity

var httpContext = new DefaultHttpContext();
//http://localhost/example
httpContext.Request.Scheme = "http";
httpContext.Request.Host = new HostString("localhost");

//Controller needs a controller context 
var controllerContext = new ControllerContext() {
    HttpContext = httpContext,
};
//assign context to controller
_controller.ControllerContext = controllerContext;

//...omitted for brevity
...