2011-07-07 53 views
1

是否可以通过约定和示例的方式设置模拟对象的期望值?MoQ +通过约定设置

I.e.

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 
} 

是否有这个的替代或没有一个需要修改源实现这一目标?另外还有一个库可以做到这一点?

回答

0

你不能用Moq做到这一点,我不知道任何可以做到这一点的图书馆。

1

您可以使用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调用内部评估中可用的表达。