如何检查称为 NSubstitute 的多个重载中的任何一个

g.p*_*dou 3 unit-testing mocking nsubstitute

设想

我想检查一个组件(sut)是否在特定条件下记录错误。注入组件的ILogger接口构造函数,Error方法有4个重载。

所以我在Arrange 中创建了一个ILogger 模拟并在Act 中使用它。

我不应该期望 sut 正在使用哪个重载,只是想期望并检查是否调用了任何重载。(这将非常白盒,并且期望远远超过功能规范。)

目前我的结论是我不能使用,.Received而是我必须为所有 4 个重载安装回调,并在其中设置一个变量,并在 Assert 部分检查该变量。

有什么简单的方法可以做到这一点我错过了吗?

(例子)

[TestMethod]
public void ShouldLogErrorIfEmailIsInvalid2()
{
    // Arrange
    var testEmailAddress = "dummy";

    //var mock = new Mock<IEMailValidator>();
    var validator = Substitute.For<IEMailValidator>();
    validator.Validate(Arg.Any<string>()).Returns(false);
    var logger = Substitute.For<ILogger>();

    var sut = new CustomerController(validator, logger);

    var customer = new Customer() { Email = testEmailAddress };

    // Act
    sut.Post(customer);

    // Assert
    // *** Here I do not want to expect a specific overload of Error, instead any of the 4 overloads satisfies the expectation
    logger.Received(1).Error(Arg.Is<string>( m => m.ToLower().Contains("email")), Arg.Any<object>());
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*pak 6

NSubstitute 没有为此提供内置语法,但可以查询所有内容ReceivedCalls()并手动断言。

例如:

var errorCalls = logger.ReceivedCalls()
    .Where(x => x.GetMethodInfo().Name == nameof(logger.Error))
    .Where(x => (x.GetArguments()[0] as string).ToLower().Contains("email"));

Assert.AreEqual(1, errorCalls.Count());
Run Code Online (Sandbox Code Playgroud)

如果这是您经常需要的东西,您可以实现一些辅助方法并将其打包成我认为相当简洁的东西。(也许static void ReceivedCallToAny(this object substitute, string methodName, Func<object[], bool> requiredArgs)有些助手喜欢T GetItemAs<T>(object[] items)访问参数?)