7

我想起订一个具有索引的属性,并且我希望能够在回调中使用索引值,就像您可以在回调中为 moq'd 方法使用方法参数一样。可能最容易用一个例子来演示:

public interface IToMoq
{
    int Add(int x, int y);
    int this[int x] { get; set; }
}

    Action<int, int> DoSet = (int x, int y) =>
    {
        Console.WriteLine("setting this[{0}] = {1}", x, y);
        throw new Exception("Do I ever get called?"); 
    };
    var mock = new Mock<IToMoq>(MockBehavior.Strict);

    //This works perfectly
    mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>()))
        .Returns<int, int>((a, b) => a + b);

    //This compiles, but my callback never seems to be called
    mock.SetupSet(m => m[It.IsAny<int>()] = It.IsAny<int>())
        .Callback(DoSet);

    var obj = mock.Object;
    Console.WriteLine("Add(3,4) => {0}", obj.Add(3, 4));  //Works perfectly
    obj[1] = 2;   //Does not throw, why? 

编辑:为了澄清,我想要getto be 的回调/返回方法,以及 to be的Func<int,int>回调/返回方法。尝试迈克的建议,您可以为 执行此操作,但有一个主要限制:setAction<int,int>set

mock.SetupSet(m => m[23] = It.IsAny<int>())
            .Callback(DoSet).Verifiable();

DoSet然后确实使用 values 调用回调(23,<any>)。不幸的是,使用It.IsAny<int>()而不是23似乎表现为0, 而不是<any>.

此外,我找不到一种调用where甚至可以编译SetupGet的方法。ReturnsReturnsFunc<int,int>

是否可以为此使用起订量?

动机:我只是在玩 Moq,试图用它来提供一个流畅的 API 来执行拦截。也就是说,给定一个接口I和一个实例XI自动创建一个Mock<I>行为默认为 的代理X

直接使用 Castle DP 可能更有意义,但我喜欢 Moq 表达式树语法。

4

2 回答 2

1

从 .NET Framework 4.5 的起订量 4.2.1502.0911 开始,我发现以下行为是正确的。

您遇到的问题特别是由于It.IsAny<T>通话。如果使用It.IsAny<T>,则回调不会执行:

[Test]
public void DoesNotExecuteCallback()
{
    // Arrange
    var mock = new Mock<IIndexable>();

    var called = false;
    mock.SetupSet(m => m[It.IsAny<int>()] = It.IsAny<int>()).Callback<int,int>((x, y) => called = true);

    var instance = mock.Object;

    // Act
    instance[1] = 2;

    // Arrange
    Assert.That(called, Is.False);
}

但是如果您使用特定参数调用它,它会调用回调:

[Test]
public void DoesExecuteCallback()
{
    // Arrange
    var mock = new Mock<IIndexable>();

    var called = false;
    mock.SetupSet(m => m[1] = 2).Callback<int,int>((x, y) => called = true);

    var instance = mock.Object;

    // Act
    instance[1] = 2;

    // Arrange
    Assert.That(called, Is.True);
}

总而言之,It.IsAny在尝试为索引器设置期望时,您应该避免使用。一般来说,你应该避免使用它,因为它鼓励草率的测试写作

有适当用例It.IsAny,但不知道我倾向于反对它的具体细节。

于 2015-04-17T13:38:50.017 回答
1

该方法SetupSet采用普通委托,而不是Expression<...>像许多其他 Moq 方法那样类型的表达式树。

出于这个原因,起订量看不到您使用了It.IsAny. 相反,It.IsAny调用(不是我们想要的)并且 Moq 只看到它的返回值,它恰好是default(int), 或0

于 2015-04-17T16:56:00.493 回答