首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FakeItEasy ControllerTest HttpGet调用

FakeItEasy ControllerTest HttpGet调用
EN

Stack Overflow用户
提问于 2020-05-07 20:54:13
回答 1查看 258关注 0票数 1

我想开始使用FakeItEasy来测试查询。我想要编写的测试应该检查HttpGet调用是否返回实体(get all和get by Id)

控制器:

代码语言:javascript
复制
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");
    }
  }
}

TestClass:

代码语言:javascript
复制
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();
  }
}

因此,在第一个测试中,我将接口IMediatR设置为返回10 ToDoItems。在调试期间,我看到_sut.Get()进入控制器,输入正确的方法/api调用。控制器中的_mediator.Send()返回一个伪IEnumerable (不是我在测试方法的第一个Call.To中设置的10个项目,而是一个不产生任何结果的枚举)。

由于result.Any()为false,控制器抛出InvalidOperationException,而我甚至不能断言result.IsNotNull()

第二个测试,我想测试调用API时是否返回1项。我设置了(a)一个int类型的itemId作为参数,(b)一个模拟的(?)列表中有1项来自itemId的设置,(c)对mediatR的调用应返回模拟的列表(b)

我从测试中进行了调用,在调试中,我看到调用await _mediator.Sent()返回ToDoItem的一个伪可枚举值,result不是null,但是因为result.Any()为false,所以没有返回该项,并且我得到了另一个InvalidOperationException

我觉得我在测试设置中遗漏了什么.一个假的数据库接口?我不想冒险让我的控制器减少if的限制,这样我的测试就能通过。

编辑:即使我将if条件更改为删除Any条件,并且我看到测试进入控制器,返回结果的"First Or Default“,测试也会失败,因为A调用肯定已经发生了。期望找到它一次或多次,但没有对伪对象进行调用。我真的不明白,我真的看到他打电话了?!

我浏览过GitHub以查找示例,但我找到的最接近的是带有方法的实体,这些方法是在接口中定义的。这不是这里的情况

由于官方文档并没有让我变得更明智,所以我求助于<3,提前谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-08 07:12:46

在第一个测试中,使用AllToDoItems类型的参数配置对Send的调用。但在控制器中,您实际上是使用TodoItemsQuery调用Send。因此调用不匹配,并且应用默认(未配置)行为,即返回一个假的IEnumerable。您需要像这样配置调用:

代码语言:javascript
复制
A.CallTo(() => _mediator.Send(A<TodoItemsQuery>._, 
           A<CancellationToken>._)).Returns(A.CollectionOfFake<ToDoItem>(10));

在第二个测试中,问题是相同的,使用ToDoItemById而不是AllToDoItems

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61658355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档