具有单一共享返回的最小起订量扩展设置

如何解决具有单一共享返回的最小起订量扩展设置

我想要做的是在模拟对象的多个方法调用上定义一个或多个Setup(s)到一个Return调用;因此避免多次调用执行 Setup().Return()

在尝试以下演示目标时,编译器提供错误,因此这不是实现该目标的合适方法

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 提到的,不是真的。但根据您的使用情况,有些选项可能会起作用。

  1. 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();
}

任何返回字符串的方法都将返回您指定的任何内容。

  1. 默认值提供程序类似但全面。
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";
    }
}
  1. 创建您自己的扩展程序;以下是一个有效的 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;
    }
}

以上所有产生以下结果

enter image description here

,

您可以在 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);

为此你需要一个额外的类:

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,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>>[] expressions)
        where T : class
        => new MultiSetup<T,TResult>(mock,expressions);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?