Moq Extended Setup with Single 共享 Return
Moq Extended Setup With Single shared Return
我想做的是定义一个或多个 Setup
(s) 到一个 Return
对模拟对象的多个方法调用的调用;因此避免了多次调用 Setup().Return()
s.
编译器在尝试以下演示目标时提供错误,因此这不是实现该目标的合适方法。
var mPlatform = new Mock<IPlatformCommunicator>();
mPlatform.Setup(mp => mp.PreStart(It.IsAny<Action<IStatus>>()))
.Setup(mp => mp.Start(It.IsAny<Action<IStatus>>()))
...
.Returns(mockStatusIndeterminate.Object as IStatus);
有没有办法在Setup
中定义多个方法调用来节省代码的总行数?
这也不是一个选项:
.Setup(mp => mp.PreStart(It.IsAny<Action<IStatus>>()) || mp.Start(It.IsAny<Action<IStatus>>()))
正如@Nkosi 所说,并非如此。但根据您的使用情况,有些选项可能会起作用。
SetReturnsDefault
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.SetReturnsDefault<string>("This is a mocked value");
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
任何 return 字符串的方法都会 return 您指定的任何内容。
- 默认值提供程序类似但全面。
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.DefaultValueProvider = new MyDefaultValueProvider();
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
public class MyDefaultValueProvider : DefaultValueProvider
{
protected override object GetDefaultValue(Type type, Mock mock)
{
return "This is my default value";
}
}
- 创建您自己的扩展;以下是一个有效的 mvp
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.Setup(new Expression<Func<IFoo, string>>[] { x => x.Bar(), x => x.Baz() }, "This is a mocked value");
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
public static class MoqExtensions
{
public static Mock<T> Setup<T, U>(this Mock<T> self, Expression<Func<T, U>>[] setups, U returns)
where T : class
{
foreach (var setup in setups)
{
self.Setup(setup).Returns(returns);
}
return self;
}
}
以上所有产生以下结果
您可以在 Mock<T>
上创建自己的扩展方法来执行您想要的操作:
public static class MoqExt {
public static void SetupReturnOnAll<T, TResult>(
this Mock<T> mock,
TResult returnValue,
params Expression<Func<T, TResult>>[] expressions)
where T: class {
foreach (var expr in expressions)
mock.Setup(expr).Returns(returnValue);
}
}
用法如下:
mPlatform
.SetupReturnOnAll(
mockStatusIndeterminate.Object as IStatus,
mp => mp.PreStart(It.IsAny<Action<IStatus>>()),
mp => mp.Start(It.IsAny<Action<IStatus>>()));
通过一些额外的努力可以改进界面:
mPlatform
.SetupAll(
mp => mp.PreStart(It.IsAny<Action<IStatus>>()),
mp => mp.Start(It.IsAny<Action<IStatus>>()))
.Return(mockStatusIndeterminate.Object as IStatus);
为此,您需要一个额外的 class:
public class MultiSetup<T, TResult>
where T: class {
public Mock<T> Mock { get; }
public Expression<Func<T, TResult>>[] Expressions { get; }
public MultiSetup(Mock<T> mock, Expression<Func<T, TResult>>[] expressions)
=> (Mock, Expressions) = (mock, expressions);
public void Return(TResult returnValue) {
foreach (var expr in Expressions)
Mock.Setup(expr).Returns(returnValue);
}
}
并且您将使用此扩展名创建它:
public static class MoqExt {
public static MultiSetup<T, TResult> SetupAll<T, TResult>(
this Mock<T> mock,
params Expression<Func<T, TResult>>[] expressions)
where T : class
=> new MultiSetup<T, TResult>(mock, expressions);
}
我想做的是定义一个或多个 Setup
(s) 到一个 Return
对模拟对象的多个方法调用的调用;因此避免了多次调用 Setup().Return()
s.
编译器在尝试以下演示目标时提供错误,因此这不是实现该目标的合适方法。
var mPlatform = new Mock<IPlatformCommunicator>();
mPlatform.Setup(mp => mp.PreStart(It.IsAny<Action<IStatus>>()))
.Setup(mp => mp.Start(It.IsAny<Action<IStatus>>()))
...
.Returns(mockStatusIndeterminate.Object as IStatus);
有没有办法在Setup
中定义多个方法调用来节省代码的总行数?
这也不是一个选项:
.Setup(mp => mp.PreStart(It.IsAny<Action<IStatus>>()) || mp.Start(It.IsAny<Action<IStatus>>()))
正如@Nkosi 所说,并非如此。但根据您的使用情况,有些选项可能会起作用。
SetReturnsDefault
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.SetReturnsDefault<string>("This is a mocked value");
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
任何 return 字符串的方法都会 return 您指定的任何内容。
- 默认值提供程序类似但全面。
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.DefaultValueProvider = new MyDefaultValueProvider();
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
public class MyDefaultValueProvider : DefaultValueProvider
{
protected override object GetDefaultValue(Type type, Mock mock)
{
return "This is my default value";
}
}
- 创建您自己的扩展;以下是一个有效的 mvp
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.Setup(new Expression<Func<IFoo, string>>[] { x => x.Bar(), x => x.Baz() }, "This is a mocked value");
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
public static class MoqExtensions
{
public static Mock<T> Setup<T, U>(this Mock<T> self, Expression<Func<T, U>>[] setups, U returns)
where T : class
{
foreach (var setup in setups)
{
self.Setup(setup).Returns(returns);
}
return self;
}
}
以上所有产生以下结果
您可以在 Mock<T>
上创建自己的扩展方法来执行您想要的操作:
public static class MoqExt {
public static void SetupReturnOnAll<T, TResult>(
this Mock<T> mock,
TResult returnValue,
params Expression<Func<T, TResult>>[] expressions)
where T: class {
foreach (var expr in expressions)
mock.Setup(expr).Returns(returnValue);
}
}
用法如下:
mPlatform
.SetupReturnOnAll(
mockStatusIndeterminate.Object as IStatus,
mp => mp.PreStart(It.IsAny<Action<IStatus>>()),
mp => mp.Start(It.IsAny<Action<IStatus>>()));
通过一些额外的努力可以改进界面:
mPlatform
.SetupAll(
mp => mp.PreStart(It.IsAny<Action<IStatus>>()),
mp => mp.Start(It.IsAny<Action<IStatus>>()))
.Return(mockStatusIndeterminate.Object as IStatus);
为此,您需要一个额外的 class:
public class MultiSetup<T, TResult>
where T: class {
public Mock<T> Mock { get; }
public Expression<Func<T, TResult>>[] Expressions { get; }
public MultiSetup(Mock<T> mock, Expression<Func<T, TResult>>[] expressions)
=> (Mock, Expressions) = (mock, expressions);
public void Return(TResult returnValue) {
foreach (var expr in Expressions)
Mock.Setup(expr).Returns(returnValue);
}
}
并且您将使用此扩展名创建它:
public static class MoqExt {
public static MultiSetup<T, TResult> SetupAll<T, TResult>(
this Mock<T> mock,
params Expression<Func<T, TResult>>[] expressions)
where T : class
=> new MultiSetup<T, TResult>(mock, expressions);
}