Мой вопрос очень похож на этот:
Как выполнить модульное тестирование действия, когда типом возврата является ActionResult?
Проблема в том, что мой вопрос смешивается в типе generic ActionResult<T>
, async
и Ok(...)
.Я не могу адаптировать ответ на связанный вопрос к общей ситуации.Или, возможно, мой сценарий несколько отличается.
Вот репродукция.Создать новое базовое веб-приложение ASP.NET типа «API».Добавьте в решение новый тестовый проект xUnit .NET Core, который ссылается на проект API (а также все необходимые библиотеки фреймворков).Создайте контроллер и выполните следующие тесты, соответственно:
public class Thing { public string Name => "Foobar"; }
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
[HttpGet]
public async Task<ActionResult<Thing>> Get()
{
// The real "Thing" would be asynchronously retrieved from the DB
return Ok(new Thing());
}
}
[Fact]
public async Task Test1()
{
var controller = new ValuesController();
var actionResult = await controller.Get();
Assert.NotNull(actionResult.Value);
Assert.Equal("Foobar", actionResult.Value.Name);
}
Вместо того, чтобы стать зелёным, этот тест не пройдёт для утверждения NotNull
(или, если яне будет иметь этого утверждения, он выдает NullReferenceException
).
После отладки и проверки иерархии классов, я обнаружил, что это, кажется, дает желаемые результаты:
[Fact]
public async Task Test1()
{
var controller = new ValuesController();
var actionResult = await controller.Get();
var okResult = actionResult.Result as OkObjectResult;
var realResult = okResult?.Value as Thing;
Assert.Equal("Foobar", realResult?.Name);
}
Но этоТакое чувство, что я делаю что-то не так.Практически у меня остались два связанных вопроса:
- Есть ли другой идиоматический способ написания этого теста, который сворачивает все эти
as
приведения? - Почему первый примеркомпилировать, но дать исключение во время выполнения?Что здесь происходит?