0

有人可以看看下面的演示代码,让我知道我看到的是由于我的错误还是 Telerik 问题?

我正在使用 Telerik.JustMock v. 2014.1.1519.1。和 Microsoft.VisualStudio.QualityTools.UnitTestFramework v. 10.0.0.0。

正如代码注释所指出的,当 id 变量相等(每个 id 调用一次)时,我得到了预期的结果,但当它们不同时却没有。当我逐步完成第一个测试时,我可以看到预期的调用正在发出,但 JustMock 然后告诉我它们没有发出。

我将不胜感激任何建设性的想法。希望这不是我睡眠不足的情况......

[TestClass]
public class RunnerTests
{
[TestMethod]
public void MakeTwoCallsDifferentIdsFails()
{
    int idOne=1;
    int idTwo=2;

    DataTable dt=new DataTable();
    dt.Columns.Add("Id");
    dt.Rows.Add(idOne);
    dt.Rows.Add(idTwo);

    IProcessor mock = Mock.Create<IProcessor>();
    Runner runner = new Runner(mock);
    runner.Process(dt);

    Mock.Assert(()=>mock.Process(Arg.IsAny<MyArgs>()), Occurs.Exactly(2));
    //The following two asserts fail (with 0 calls made to mock), regardless of sequence:
    Mock.Assert(()=>mock.Process(Arg.Matches<MyArgs>     
       (d=>d.Id==idOne)),Occurs.Once());
    Mock.Assert(()=>mock.Process(Arg.Matches<MyArgs>
       (d=>d.Id==idTwo)),Occurs.Once());
}

[TestMethod]
public void MakeTwoCallsSameIdPasses()
{
    //ids intentionally equal:
    int idOne=1;
    int idTwo=1;

    DataTable dt=new DataTable();
    dt.Columns.Add("Id");
    dt.Rows.Add(idOne);
    dt.Rows.Add(idTwo);

    IProcessor mock = Mock.Create<IProcessor>();
    Runner runner = new Runner(mock);
    runner.Process(dt);

    //all asserts pass:
    Mock.Assert(()=>mock.Process(Arg.IsAny<MyArgs>()), Occurs.Exactly(2));
    //The following two pass:
    Mock.Assert(()=>mock.Process(Arg.Matches<MyArgs>     
        (d=>d.Id==idOne)),Occurs.Exactly(2));
    Mock.Assert(()=>mock.Process(Arg.Matches<MyArgs>
        (d=>d.Id==idTwo)),Occurs.Exactly(2));
}
}

public interface IProcessor
{
    void Process(MyArgs args);
}

public class MyArgs
{
    public void UpdateId(int newId)
    {
        this.Id = newId;
    }

    public int Id {get; private set;}
}

public class Runner
{
    private IProcessor processor;

    public Runner(IProcessor processor)
    {
        this.processor=processor;
    }

    public void Process(DataTable dt)
    {
        MyArgs args = new MyArgs();

        foreach(DataRow row in dt.Rows)
        {
            int id = Convert.ToInt32(row["Id"]);
            args.UpdateId(id);
            processor.Process(args);
        }
    }
}

编辑:在失败的测试方法中,如果我完全删除一个 int 变量并明确断言另一个变量只被调用一次,则测试通过。只有当我将第二个不同的价值投入其中时,事情似乎才会向南发展。

4

2 回答 2

0

模拟记录了它被相同的实例调用了两次MyArgs。但是,这两个调用之间的实例内容不同的事实却被它忽略了。当您到达断言调用的位置时,记录的MyArgs参数Id在失败的测试中等于 2。

如果您将Process方法更改为

public void Process(DataTable dt)
{
    foreach(DataRow row in dt.Rows)
    {
        MyArgs args = new MyArgs();
        int id = Convert.ToInt32(row["Id"]);
        args.UpdateId(id);
        processor.Process(args);
    }
}

两个测试都会通过。

编辑:

您可以通过在安排中陈述您的期望来使用 JustMock 获得所需的行为,如下所示:

[TestMethod]
public void MakeTwoCallsDifferentIdsFails()
{
    int idOne = 1;
    int idTwo = 2;

    DataTable dt = new DataTable();
    dt.Columns.Add("Id");
    dt.Rows.Add(idOne);
    dt.Rows.Add(idTwo);

    IProcessor mock = Mock.Create<IProcessor>();
    Mock.Arrange(() => mock.Process(Arg.Matches<MyArgs>(d => d.Id == idOne))).OccursOnce();
    Mock.Arrange(() => mock.Process(Arg.Matches<MyArgs>(d => d.Id == idTwo))).OccursOnce();

    Runner runner = new Runner(mock);
    runner.Process(dt);

    Mock.Assert(mock);
}

这样做的原因是,一旦发生正确的调用,就会将发生预期标记为满足,因此谓词Arg.Matches与传递给方法的参数的实时值一起工作,而不是在保存的参数实例可能发生突变时事后处理.

于 2015-03-31T07:22:35.853 回答
0

由于我无法让我们选择的模拟框架(JustMock)来完成我想要的,我最终应用了KISS,忘记了这个测试的模拟框架,并使用了如下内容:

我将测试方法更改为如下所示:

    [TestMethod]
    public void TwoCallsDifferentIds()
    {
        int idOne = 1;
        int idTwo = 2;

        DataTable dt = new DataTable();
        dt.Columns.Add("Id");
        dt.Rows.Add(idOne);
        dt.Rows.Add(idTwo);
        FakeProcessor processor = new FakeProcessor();
        Runner runner = new Runner(processor);
        runner.Process(dt);

        Assert.AreEqual(2, processor.MyArgsIds.Count);
        Assert.AreEqual(1, processor.MyArgsIds[0]);
        Assert.AreEqual(2, processor.MyArgsIds[1]);
    }

并添加了以下假货:

public class FakeProcessor : IProcessor
{
    private IList<int> mList = new List<int>();

    public IList<int> MyArgsIds 
    {
        get { return mList; }
    }

    public void Process(MyArgs args)
    {
        mList.Add(args.Id);
    }
}

也许没有那么光滑,但它让我得到了我想要的测试。

于 2015-03-31T17:10:27.410 回答