WithArgumentsForConstructor 与 A<string>.That.Contains

WithArgumentsForConstructor with A<string>.That.Contains

我想测试执行是否调用了一个 方法,其中的字符串包含 给定部分,并且 class 的实例化包含(在它的构造函数) 给定字符串的一部分。

[TestMethod]
public void TestMethod1()
{
    // Arrange
    var fakeLogger = A.Fake<ILogger>();
    var loggerExecutor = new LoggerExecutor(fakeLogger);

    // Act
    loggerExecutor.Log();

    // Assert
    A.CallTo(() => fakeLogger.Error(A<string>.That.Contains("string")).MustHaveHappenedOnceExactly();
    A.CallTo(() => fakeLogger.Error(
        A.Fake<LogLine>(x => x.WithArgumentsForConstructor(() => A<string>.That.Contains("LogLine"))))
    ).MustHaveHappenedOnceExactly();
}

public class LoggerExecutor
{
    private readonly ILogger _logger;

    public LoggerExecutor(ILogger logger)
    {
        _logger = logger;
    }

    public void Log()
    {
        _logger.Error("With string parameter");
        _logger.Error(new LogLine("With LogLine parameter"));
    }
}

第一个带有字符串对象的断言有效。但是,当我尝试测试第二个断言时,它失败并出现以下异常:

System.InvalidOperationException: An argument constraint, such as That, Ignored, or _, cannot be nested in an argument.
at FakeItEasy.Expressions.ExpressionArgumentConstraintFactory.ArgumentConstraintExpressionVisitor.VisitMember(MemberExpression node)

我应该尝试使用假对象以避免在测试中重复所有字符串。

日志行class:

public class LogLine
{
    public readonly string Message;

    public readonly object[] Params;

    public static implicit operator LogLine(string message)
    {
        return new LogLine(message ?? string.Empty);
    }

    public LogLine(string message, params object[] @params)
    {
        Message = message;
        Params = @params;
    }
}

测试:

FakeItEasy 无法判断传递给方法的对象是如何构造的。第二个 _logger.Error 调用传递了一个 LogLine 的实例,因此我认为您想检查该对象本身。具体可以看Message属性.

尝试

A.CallTo(() => fakeLogger.Error(
        A<LogLine>.That.Matches(ll => ll.Message.Contains("LogLine")))
    ).MustHaveHappenedOnceExactly();