c# - 通过 Moqs It.IsAny作为方法参数
问题描述
首先是关于我的开发环境的一些信息:
- .Net 框架 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
至作为未知类型时,anyString
变量null
在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 ) );
}
解决方案
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);
//...
}