在这种情况下如何使用模拟?

时间:2011-03-31 08:59:13

标签: c# unit-testing moq n-tier-architecture

这是我的问题:

我有一个n层应用程序,我必须编写单元测试。单元测试用于业务层。

我有一个测试名为Insert()的方法,这个方法使用两个受保护的继承方法,直接调用数据访问层的方法。

所以我为DAL制作了一个模拟对象。但是重要的是,在继承的(edit :) protected 方法中,它将使用来自DAL的另一个对象!似乎无法模仿这个!

以下是测试代码的方法:

public int Insert(MYOBJECT aMyObject)
    {
            //first inherited method use the FIRSTDALOBJECT so the mock object --> No problem
            aMyObject.SomeField= FirstInherited();

            //Second inherited method (see after) --> my problem
            aMyObject.SomeOtherField = SecondInherited();

            // Direct access to DALMethod, use FIRSTDALOBJECT so the mock -->No Problem
            return this.FIRSTDALOBJECT.Insert(aMyObject);             
     }

这是SecondInherited方法:

 protected string SecondInherited ()
    { 
        // Here is my problem, the mock here seems not be possible for seconddalobject                                          
        return ( new SECONDDALOBJECT Sdo().Stuff());
    }

这是单元测试方法代码:

    [TestMethod()]
    public void InsertTest()
    {
        BLLCLASS_Accessor target = new BLLCLASS_Accessor();
        MYOBJECT aMyObject = new MYOBJECT { SomeField = null, SomeOtherField = 1 };
        int expected = 1;
        int actual;

        //mock
        var Mock = new Mock<DAL.INTERFACES.IFIRSTDALOBJECT>();
        //Rec for calls
        List<SOMECLASS> retour = new List<SOMECLASS>();
        retour.Add(new SOMECLASS());

        //Here is the second call (last from method to test)
        Mock
            .Setup(p => p.Insert(aMyObject))
            .Returns(1);

        // Here is the first call (from the FirstInherited())
        Mock
            .Setup(p => p.GetLast())
            .Returns(50);
        // Replace the real by the mock
        target.demande_provider = Mock.Object;

        actual = target.Insert(aMyObject);
        Assert.AreEqual(/*Some assertion stuff*/);
    }

感谢您阅读所有问题:-)希望它足够清楚。

2 个答案:

答案 0 :(得分:3)

您的文字似乎表示SecondInheritedprivate,而在代码示例中则为protected。无论如何,如果它不是protected,我建议将其访问限定符更改为第一步。

您可以创建一个仅用于测试目的的子类,并覆盖SecondInherited那里以避免创建SECONDDALOBJECT并返回一些适合您的测试的值。

通过这种方式,您可以编写您的第一个单元测试,对所测试的类进行最小的更改,从而最大限度地减少破坏的可能性。一旦您进行了单元测试,这些就可以让您安全地进行更多重构,最终实现更好(更可测试/可模拟)的设计,例如使用Dependency Injection或工厂。 (我可能更喜欢Abstract Factory而不是Factory Method,因为后者实际上会迫使你继续对测试类进行子类化。)

学习这项技术的基本的,强烈推荐的书(以及更多)是Working Effectively With Legacy Code

答案 1 :(得分:2)

没有机会用MOQ嘲笑这个。 您有两种选择:

  1. 使用TypeMock或Moles模拟SECONDDALOBJECT
  2. 重构代码,因此SECONDDALOBJECT的实例不是以它的方式创建的,而是以可以模拟的方式创建(工厂方法,DI,...)(首选!)