Passing Moqs It.IsAny<string> as method argument

五迷三道 提交于 2021-02-08 15:01:27

问题


First some information about my development environment:

  • .Net Framework 4.5
  • Moq 4.10
  • Autofac 4.2
  • NUnit 3.11

I try to mock a function that takes some string arguments and I would like to use It.IsAny<string>() to setup. Normally I would to that like this:

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

But now I would like to call a fucntion that makes the setup, so I do not have to copy paste the code above and make my unit tests a little bit "better looking". I imagine something like this:

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 ) );     
}

Does someone know a solution for that? I when I use string or even var as Unknown type the variable anyString hold the value null after UnknownType anyString = It.IsAny<string>();. Thanks in advance for your answers.

Further description:

I need to specify different values for every argument. So It could look like this:

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:


It.* is meant to be used as Setup expression arguments and not passed around as parameters/variables as, by default, they return null.

To the best of my knowledge, what you are requesting does not appear to be possible.

The closest thing I can think of through the use of generics is to create an extension method to act on the auto mock that takes the desired expression to mock

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);
    }
}

which really does not save you much in terms or repeated code as you will still have to invoke It.* in the expression

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

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

    //...           
}

Original Answer

Use generics

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

which would then let you invoke the setup as needed like

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


来源:https://stackoverflow.com/questions/53003652/passing-moqs-it-isanystring-as-method-argument

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!