首页 > 解决方案 > 调用 FakeItEasy 模拟 mediatr.send 方法失​​败断言

问题描述

我是 FakeItEasy 的新手,我在断言是否调用了异步方法时遇到了问题。它失败了断言,因为它还没有被调用。我已尽力确保断言与配置的调用匹配,但仍然没有骰子。

        [HttpPost]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status201Created)]
        public async Task<IActionResult> Post(CreateOwnerRequest requestModel)
        {
            var command = new CreateOwnerCommand { RequestModel = requestModel };
            var ownerResponse = await _mediator.Send(command, default);
                       
            //TODO: return URI for the new resources
            return Created("", ownerResponse);
        }
        [Theory]
        [ClassData(typeof(ValidCreateOwnerTestData))]
        public async void ShouldCallCreateOwnerHandler(CreateOwnerRequest validCreateOwnerModel)
        {
            // Arrange
            var fakeMediator = A.Fake<IMediator>();
            A.CallTo(() => fakeMediator.Send(new CreateOwnerCommand { RequestModel = validCreateOwnerModel },
                default)).Returns(A.Dummy<Task<OwnerResponse>>());
            var ownerController = new OwnerController(fakeMediator);

            // Act
            _ = await ownerController.Post(validCreateOwnerModel);

            // Assert
            A.CallTo(() => fakeMediator.Send(new CreateOwnerCommand { RequestModel = validCreateOwnerModel },
                default)).MustHaveHappened();
        }
    public class ValidCreateOwnerTestData : IEnumerable<object[]>
    {
        public IEnumerator<object[]> GetEnumerator()
        {
            yield return new object[] { new CreateOwnerRequest { FirstName = "Foo", LastName = "Bar" } };
        }

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }

标签: unit-testingcontrollerxunitmediatrfakeiteasy

解决方案


在您的断言中,您创建了一个CreateOwnerRequest. 显然,这与控制器操作中实际使用的实例不同,因此它不被视为相等,并且断言失败。

可以覆盖EqualsonCreateOwnerRequest以使它们被视为相等,但这可能不是一个好主意,因为您这样做只是为了满足断言。

更好的方法是使用参数约束来指定参数必须匹配的条件:

// Assert
A.CallTo(() => fakeMediator.Send(
    A<CreateOwnerCommand>.That.Matches(command => /* some condition here */))
    A<CancellationToken>.Ignored))
    .MustHaveHappened();

(请注意,我也更改defaultA<CancellationToken>.Ignored,因为如果控制器操作开始使用真正的取消令牌,您可能不希望断言失败......)


推荐阅读