调用 FakeItEasy 模拟的 mediatr.send 方法断言失败

Call to FakeItEasy mocked mediatr.send method fails assertion

我是 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();
    }

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

可以 覆盖 CreateOwnerRequest 上的 Equals 以便它们被认为是相等的,但这可能不是一个好主意,因为您只会这样做为了满足断言。

更好的方法是使用argument constraints指定参数必须匹配的条件:

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

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