Я хочу начать использовать FakeItEasy для тестирования запросов. Тесты, которые я хочу написать, должны проверять, возвращаются ли объекты при вызовах HttpGet (получить все и получить по идентификатору).
Контроллер:
public class ToDoController : ControllerBase
{
private readonly IMediator _mediator;
public ToDoController(IMediator mediator) =>
_mediator = mediator;
[HttpGet]
[Produces("application/json")]
[ProducesResponseType(typeof(IEnumerable<ToDoItem>), (int)HttpStatusCode.OK)]
public async Task<ActionResult<IEnumerable<ToDoItem>>> Get()
{
var result = await _mediator.Send(new ToDoItemsQuery(new
AllToDoItems())).ConfigureAwait(false);
if (result != null && result.Any())
{
return result.ToList();
}
throw new InvalidOperationException("TODO: error handling");
}
[HttpGet]
[Route("{id}")]
[Produces("application/json")]
[ProducesResponseType(typeof(ToDoItem), (int)HttpStatusCode.OK)]
public async Task<ActionResult<ToDoItem>> GetById(int itemId)
{
var result = await _mediator
.Send(new ToDoItemsQuery(new ToDoItemById(itemId)))
.ConfigureAwait(false);
if (result != null && result.Any())
{
return result.FirstOrDefault();
}
throw new InvalidOperationException("TODO: error handling");
}
}
}
Тестовый класс:
public class ToDoItemControllerTests : ControllerTestBase
{
private IMediator _mediator;
private ToDoController _sut;
public ToDoItemControllerTests()
{
_mediator = A.Fake<IMediator>();
_sut = new ToDoController(_mediator);
}
[TestMethod]
public async Task GetAllItemsAsync_SuccessTest()
{
A.CallTo(() => _mediator.Send(A<AllToDoItems>._,
A<CancellationToken>._)).Returns(A.CollectionOfFake<ToDoItem>(10));
var result = await _sut.Get();
Assert.IsNotNull(result);
A.CallTo(() => _mediator).MustHaveHappened();
}
[TestMethod]
public async Task GetItemByIdAsync_SuccessTest()
{
// Arrange
int itemId = 2;
var commandResult =
new List<ToDoItem>
{
new ToDoItem
{
Id = itemId
};
}
A.CallTo(() => MediatR.Send(A<ToDoItemById>._, A<CancellationToken>._)).Returns(commandResult);
// Act
var result = await _sut.GetById(itemId);
// Assert
Assert.IsNotNull(result);
A.CallTo(() => MediatR.Send(A<ToDoItemById>._, A<CancellationToken>._)).MustHaveHappened();
}
}
Итак, в первом тесте я настроил A.CallTo интерфейса IMediatR для возврата 10 элементов ToDoItem. Во время отладки я вижу, как _sut.Get() входит в контроллер, вводя правильный вызов метода/API. _mediator.Send() в контроллере возвращает Fake IEnumerable (не 10 элементов, которые я установил в первом Call.To в тестовом методе, а перечисление, которое не дает результатов).
Из-за того, что result.Any() является ложным, контроллер выдает InvalidOperationException, и я даже не могу подтвердить результат.IsNotNull()
Второй тест, который я хочу проверить, возвращается ли 1 элемент при вызове API. Я установил (a) itemId типа int для параметра, (b) имитированный (?) Список с 1 элементом из настройки с itemId и (c) вызов mediatR должен возвращать имитированный Listfrom (b)
Я делаю вызов из теста, в отладке я вижу вызов await _mediator.Sent(), возвращающий Fake Ienumerable of ToDoItem, результат не равен нулю, но поскольку результат.Any() имеет значение false, элемент не возвращается, и я получаю еще одно исключение InvalidOperationException
Я чувствую, что что-то упускаю в настройке тестов. Поддельный интерфейс базы данных? Я не хочу рисковать своим контроллером и делать его менее строгим, просто чтобы мой тест прошел
РЕДАКТИРОВАТЬ: даже если я изменю условие if на удаление условия Any и увижу, что тест входит в контроллер, возвращая результат «Первый или по умолчанию», тест завершается неудачей при вызове, который должен был произойти. Ожидалось, что он будет найден один или несколько раз, но никаких обращений к фальшивому объекту не было. Этого я действительно не понимаю, я действительно вижу, как он звонит?!
Я просмотрел GitHub, чтобы найти примеры, но наиболее близкими, которые я нашел, были сущности с методами, причем эти методы были определены в интерфейсе. Это не тот случай
Поскольку официальная документация не делает меня мудрее, я обращаюсь к SO ‹3 Заранее спасибо!