需要根据所设置属性的期望来控制方法期望的顺序

时间:2014-07-24 21:38:08

标签: c# rhino-mocks

我有以下示例,其行为方式与我的预期不同。

public abstract class Example
{
    public abstract string Foo();

    public List<string> Bar()
    {
        PreMethod();

        var list = new List<string>();

        var stack = new Stack<string>();
        foreach (var item in Stuff)
        {
            stack.Push(item);
        }

        while (stack.Any())
        {
            SomeThing = stack.Pop();
            var f = Foo();
            list.Add(f);
        }

        PostMethod();
        return list;
    }

    public abstract void PreMethod();

    public abstract void PostMethod();

    public abstract IEnumerable<string> Stuff { get; }

    public abstract string SomeThing { set; get; }
}

[TestClass]
public class ExampleTest
{
    private Example example;

    private MockRepository mocks;

    [TestInitialize]
    public void InitializeTest()
    {
        mocks = new MockRepository();
        example = MockRepository.GeneratePartialMock<Example>();
    }

    [TestMethod]
    public void BarTest()
    {
        using (mocks.Ordered())
        {
            example.Expect(e => e.PreMethod());
            example.Expect(e => e.Stuff).Return(new[] { "One", "Two" });

            using (mocks.Unordered())
            {
                using (mocks.Ordered())
                {
                    example.Expect(e => e.SomeThing).SetPropertyWithArgument("One");
                    example.Expect(e => e.Foo()).Return("one");
                }

                using (mocks.Ordered())
                {
                    example.Expect(e => e.SomeThing).SetPropertyWithArgument("Two");
                    example.Expect(e => e.Foo()).Return("two");
                }
            }


            example.Expect(e => e.PostMethod());
        }

        mocks.ReplayAll();


        var actual = example.Bar();
        Assert.AreEqual(2, actual.Count);
        Assert.AreEqual("two", actual[0]);
        Assert.AreEqual("one", actual[1]);
    }
}

因此,期望通过将SomethingFoo的调用置于using(mocks.Ordered)内,Foo将根据Something返回值刚设置,但测试失败,因为结果列表实际上有“一”,然后“两”。当我调试时,我发现在Something设置为“2”之后,对Foo的调用将返回“1”。基本上我只想让Foo的返回与Something所设置的相关联,但不知道它们将被设置的顺序(基本上这个测试不应该通过改变它来实现使用队列而不是堆栈的代码。

1 个答案:

答案 0 :(得分:0)

所以我发现的第一件事是订购不适用于AAA风格。其次,我发现我可以使用WhenCalled来实现我所寻找的目标。

    [TestMethod]
    public void BarTest()
    {
        example.Expect(e => e.PreMethod());
        example.Expect(e => e.Stuff).Return(new[] { "One", "Two" });
        example.Expect(e => e.SomeThing)
            .SetPropertyWithArgument("One")
            .WhenCalled(obj => example.Expect(e => e.Foo()).Return("one"));
        example.Expect(e => e.SomeThing)
            .SetPropertyWithArgument("Two")
            .WhenCalled(obj => example.Expect(e => e.Foo()).Return("two"));
        example.Expect(e => e.PostMethod());

        var actual = example.Bar();

        Assert.AreEqual(2, actual.Count);
        Assert.AreEqual("two", actual[0]);
        Assert.AreEqual("one", actual[1]);
        example.VerifyAllExpectations();
    }

通过将期望置于WhenCalled之内,它确保期望按预期顺序发生。