MoQ +设置通过约定

本文关键字:约定 设置 MoQ | 更新日期: 2023-09-27 18:01:39

是否有可能通过约定和示例模式来设置模拟对象的期望?

class Foo
{
     public virtual int? Abc { get; set; } // <-- Convention: Ignore nullable if null 
     public virtual string Xyz { get; set; } // <-- Convention: Ignore null
     public virtual int Dingdong { get; set; } // <-- Convention: Ignore if greater than 10
}

是否有替代方案,或者必须修改源代码才能实现这一点?或者有一个库可以做到这一点吗?

MoQ +设置通过约定

您可以使用It.Is(..)表达式在您的AssemblyInitialize中定义一组约定,并在您的测试设置中使用它们。

围绕它定义一些辅助方法也很容易。例如,可以用ItExt.IsConventional<T>()方法镜像It.IsAny<T>()语法。下面是一个可能的实现:

public static class ItExt
{
    private static readonly Dictionary<Type, object> RegisteredConventions = new Dictionary<Type, object>();
    public static void RegisterConvention<T>(Func<T> convention)
    {
        RegisteredConventions.Add(typeof(T), convention);
    }
    public static T IsConventional<T>()
    {
        Func<T> conventionFunc = (Func<T>)RegisteredConventions[typeof(T)];
        return conventionFunc();
    }
}

和用法:

[TestClass]
public class FooTests
{
    [AssemblyInitialize]
    public static void AssemblyInitialize(TestContext context)
    {
        ItExt.RegisterConvention(() => It.Is<int?>(n => n.HasValue));
    }
    [TestMethod]
    public void FooTest()
    {
        // Arrange
        Mock<IFoo> fooMock = new Mock<IFoo>();
        fooMock.Setup(f => f.Bar(ItExt.IsConventional<int?>()))
               .Verifiable();
        // Act
        fooMock.Object.Bar(1);
        // Assert
        fooMock.VerifyAll(); // throws
    }
}

注意约定定义必须存储为Func<T>,以便表达式可以在Mock<T>.Setup调用中求值。

你不能用Moq做到这一点,我不知道有任何库可以做到这一点。