将Moqs It.IsAny <string>作为方法参数传递

时间:2018-10-26 07:31:46

标签: c# moq

首先,有关我的开发环境的一些信息:

  • .Net Framework 4.5
  • 起订量4.10
  • Autofac 4.2
  • NUnit 3.11

我尝试模拟一个需要一些字符串参数的函数,我想使用It.IsAny<string>()进行设置。通常我会这样:

using ( AutoMock mock = AutoMock.GetLoose() ) {
    mock.Mock<SomeInterface>()
                .Setup( x => x.someFunction(
                    It.IsAny<string>(),
                    It.IsAny<string>(),
                    It.IsAny<string>() ) );
//...
}

但是现在我想调用一个进行设置的功能,因此我不必复制粘贴上面的代码并使我的单元测试稍微“好看”。我想像这样:

using ( AutoMock mock = AutoMock.GetLoose() ) {
    UnknownType anyString = It.IsAny<string>();
    setup( mock, anyString );
//...
}

void setup( Automock mock, UnknownType anyString ){
    mock.Mock<SomeInterface>()
            .Setup( x => x.someFunction( anyString, anyString, anyString ) );     
}

有人知道解决方案吗?当我使用string甚至是var作为Unknown类型时,变量anyStringnull之后保留值UnknownType anyString = It.IsAny<string>();。预先感谢您的回答。

进一步的描述:

我需要为每个参数指定不同的值。所以它可能看起来像这样:

using ( AutoMock mock = AutoMock.GetLoose() ) {
   UnknownType string1 = It.IsAny<string>;
   UnknownType string2 = It.Is<string>( s => s.Equals( "Specific string" )  );
   UnknownType string3 = It.IsAny<string>;
   setup( mock, string1, string2, string3 );
//...           
}

private static void setup( AutoMock mock, 
   UnknownType string1, UnknownType string2, UnknownType string3 ) {
   mock.Mock<SomeInterface>().Setup( x => x.someFunction( string1, string2, string3 ) );
}

1 个答案:

答案 0 :(得分:3)

It.*被用作Setup表达式参数,而不是作为参数/变量传递,因为默认情况下,它们返回 null

据我所知,您所要求的似乎无法实现。

通过使用泛型,我能想到的最接近的事情是创建一个扩展方法,以对需要所需表达式进行模拟的自动模拟进行操作

public static class AutomockExtension {
    public static Moq.Language.Flow.ISetup<T> Setup<T>(this Automock mock, Expression<Action<T>> expression) where T : class {
        return mock.Mock<T>().Setup(expression);
    }

    public static Moq.Language.Flow.ISetup<T, TValue> Setup<T, TValue>(this Automock mock, Expression<Func<T, TValue>> expression) where T : class {
        return mock.Mock<T>().Setup(expression);
    }
}

这样做确实不会为您节省很多用语或重复代码,因为您仍然必须在表达式中调用It.*

using ( AutoMock mock = AutoMock.GetLoose() ) {

    mock.Setup<SomeInterface>(_ => 
        _.someFunction(
            It.IsAny<string>(),
            It.Is<string>( s => s.Equals( "Specific string" ),
            It.IsAny<string>()
        ) 
    );

    //...           
}

原始答案

使用泛型

void setup<T>(Automock mock){
    mock.Mock<SomeInterface>()
            .Setup(_ => _.someFunction(
                It.IsAny<T>(), 
                It.IsAny<T>(), 
                It.IsAny<T>()));     
}

然后您可以根据需要调用设置,例如

using ( AutoMock mock = AutoMock.GetLoose() ) {
    setup<string>(mock);
    //...
}