Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Moqs It.IsAny<string> as method argument

Tags:

c#

moq

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 ) );
}
like image 252
Blackbriar Avatar asked Oct 26 '18 07:10

Blackbriar


1 Answers

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);
    //...
}
like image 51
Nkosi Avatar answered Nov 15 '22 18:11

Nkosi