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

本文关键字:期望 属性 控制 顺序 方法 设置 | 更新日期: 2023-09-27 18:14:46

我有一个下面的例子,它没有按照我期望的方式运行。

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刚刚设置的值返回值,但是测试失败,因为结果列表实际上有"1",然后是"2"。当我调试时,我看到Something被设置为"二"后,对Foo的调用返回"一"。基本上,我只是想使Foo的返回连接到Something被设置为,但不知道它们将被设置的顺序(基本上这个测试不应该通过更改代码来使用队列而不是堆栈来影响)。

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

所以我发现的第一件事是排序不适用于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中,它确保期望按照预期的顺序发生。