如何在Rhino Mock AAA中模拟其他类的方法调用?

时间:2009-09-23 03:27:39

标签: rhino-mocks

我有以下代码(简化)。

public class OrderProcessor
{
    public virtual string PlaceOrder(string test)
    {
        OrderParser orderParser = new OrderParser();
        string tester =  orderParser.ParseOrder(test);
        return tester + " here" ;
    }

}

public class OrderParser
{

    public virtual string ParseOrder(string test)
    {
        if (!string.IsNullOrEmpty(test.Trim()))
        {
            if (test == "Test1")
                return "Test1";
            else
            {
                return "Hello";
            }
        }
        else
            return null;
    }
}

我的测试如下 -

   public class OrderTest
   {
      public void TestParser()
      {
        // Arrange

        var client = MockRepository.GenerateMock<OrderProcessor>();
        var spec = MockRepository.GenerateStub<OrderParser>();

        spec.Stub(x => x.ParseOrder("test")).IgnoreArguments().Return("Test1");

        //How to pass spec to client so that it uses the same.

        }
    }

现在我如何测试客户端,以便它使用OrderParser中的模拟方法。 我可以模拟OrderParser,但是如何将它传递给orderProcessor模拟类?

请告诉我。

提前致谢。

1 个答案:

答案 0 :(得分:1)

我对你的测试感到有点困惑,因为除了RhinoMocks工作之外,你并没有真正测试任何东西。你创建两个模拟,然后对它们做一些断言。你甚至没有测试过真正的课程。

如果你真的想要获得一个好的单元测试,你需要做一些依赖注入。您可以快速重构代码以使用接口和依赖注入来使测试有效。

首先从OrderParser类中提取界面:

public interface IOrderParser
{
    String ParseOrder(String value);
}

现在确保您的OrderParser类实现该接口:

public class OrderParser: IOrderParser{ ... }

现在,您可以重构OrderProcessor类,以通过其构造函数接收IOrderParser对象的实例。通过这种方式,您可以将依赖项“注入”类中。

public class OrderProcessor
{
    IOrderParser _orderParser;

    public OrderProcessor(IOrderParser orderParser)
    {
        _orderParser = orderParser;
    }

    public virtual string PlaceOrder(string val)
    {
        string tester =  _orderParser.ParseOrder(val);
        return tester + " here" ;
    }
}

在您的测试中,您只想模拟依赖项,而不是SUT(测试对象)。你的测试看起来像这样:

   public class OrderTest
   {
      public void TestParser()
      {
        // Arrange

        var spec = MockRepository.GenerateMock<IOrderParser>();
        var client = new OrderProcessor(spec);

        spec.Stub(x => x.ParseOrder("test")).IgnoreArguments().Return("Test1");

        //Act
        var s = client.PlaceOrder("Blah");

        //Assert
        Assert.AreEqual("Test1 Here", s);

        }
    }

我很难衡量你要对你的课程做什么,但你应该能够从中得到这个想法。一些公理要遵循:

  1. 使用接口和组合而不是继承
  2. 使用dependency injection进行外部依赖(控制反转)
  3. 测试单个单元,并模拟其依赖项
  4. 仅模拟一个级别的依赖项。如果您正在测试依赖于Z的X类,那么您应该只是模仿Y而不是Z.
  5. 始终test behavior且永远不会实施细节
  6. 你似乎走在正确的轨道上,但需要一点指导。我建议阅读Martin FowlerBob Martin必须加快速度的材料。