代码之家  ›  专栏  ›  技术社区  ›  jpoh

我需要测试助手/设置方法吗?

  •  3
  • jpoh  · 技术社区  · 16 年前

    所以我有一个helper方法,它看起来像下面这样:

    private D GetInstanceOfD(string param1, int param2)
    {
        A a = new A();
        B a = new B();
        C c = new C(a,b, param1);
    
        return new D(c, param2);
    }
    

    它只是一个方便的助手方法,我可以调用它来获取我需要的特定对象,而不是记住我需要连接哪些依赖项来获取我需要的对象。

    我的第一个问题是:像这样的方法应该被测试吗?我想测试这些类型的方法的唯一原因是确保使用了正确的依赖项,并且正确地设置了依赖项。

    如果第一个问题的答案是“是”,我的第二个问题是:如何回答?我目前使用的是Nunit和Rhinomocks,我正在尝试解决如何重构这个方法才能进行测试(好吧,以及是否应该测试类似的东西!);依赖项注入显然不会在这里工作,因为此方法实际上创建了依赖项!

    或者使用这种方法是不好的做法,我应该这样做:

    D d = new (new C(new A(), new B(), "string"), 1024);
    
    5 回复  |  直到 16 年前
        1
  •  1
  •   tvanfosson    16 年前

    首先,该方法是私有的,因此,通常我会说,该方法可能不需要直接进行测试。即使它是用于实际代码的辅助方法,而不是用于测试的辅助方法,也可能只希望通过公共接口间接测试它。

    第二,如果您确实想测试它——也许无论如何——您应该考虑使用工厂来创建对象,而不是直接实例化对象。结合使用工厂和接口,可以将依赖项抽象出来。只需将工厂注入包含此方法的类的构造函数中,并将其用作此方法中的属性来创建适当的对象。如果你走这条路,你也会发现工厂也是逻辑创建D的地方。

    如果代码是生产代码的话,这绝对是我的方向。下面的例子:

    public class ObjectFactory 
    {
         public virtual A CreateA() { return new A(); }
         public virtual B CreateB() { return new B(); }
         public virtual C CreateC( string str ) { return new C( CreateA(), CreateB(), str );
         public virtual D CreateD( string str, int num )
         {
             return new D( CreateC( str ), num );
         }
    }
    
    
    public class Foo
    {
        private ObjectFactory ObjectFactory { get; set; }
    
        public Foo() : this(null) { }
        public Foo( ObjectFactory factory )
        {
             this.ObjectFactory = factory ?? new ObjectFactory();
        }
    
        public void Bar()
        {
            D objD = this.ObjectFactory.CreateD( param1, param2 );
        }
    }
    
    [TestMethod]
    public void TestBar()
    {
         var factory = MockRepository.GenerateMock<ObjectFactory>();
         var d = MockRepository.GenerateMock<D>();
         factory.Expect( f => f.CreateD( "abc", 10 ) ).Return( d );
    
         var foo = new Foo( factory );
    
         foo.Bar();
    
         factory.VerifyAllExpectations();
         d.VerifyAllExpectations();
    }
    
        2
  •  3
  •   JaredPar    16 年前

    要回答您的第一个问题,是的,您应该测试这个方法。测试这个方法要比写整个帖子花费更少的精力,并且会给你关于运输代码的验证。

    就如何实现这一点而言,这取决于你打算用这种方法做什么。以下是假设函数行为合理的情况下可以测试的内容

    • 如果我为第一个参数传递NULL,会发生什么?
    • 如果给第二个参数传递一个负数,会发生什么?
    • getInstanceOfd是否在预期的情况下实际返回d?
    • d是否具有给定输入的正确值。
    • 假设C、A和B实例是可访问的呢?
        3
  •  2
  •   Jon Limjap    16 年前

    当你遇到这样的问题时,记住一件好事就是 小事一桩 .

    设置方法需要很简单。拆卸方法必须是琐碎的。辅助方法可以是非常重要的——如果它们有自己的测试集。

    如果单元测试本身变得如此复杂, 需要 为了测试它们,你做错了。

        4
  •  1
  •   Carl Manaster    16 年前

    你应该测试这个方法。你应该测试它,因为它可能会失败;一条xp格言是 测试所有可能损坏的部件 .

    现在,这并不意味着您必须为它创建新的测试;它可以通过其他方法间接地进行测试。如果它是在重构过程中提取的,那么它可能已经过测试。

    如果需要,测试它的一种方法是将它提取到一个助手类中,在该类中它不是私有的,并将其拆分为多个函数,以便能够注入依赖项。

    //--- don't write this, you'll probably regret it ;o)
    D d = new (new C(new A(), new B(), "string"), 1024);
    
        5
  •  0
  •   aberrant80    16 年前

    private 方法通常是不需要直接测试的指示器,因为您将测试使用这些方法的方法 私有的 方法。

    该方法感觉像是属于工厂类或生成器类,而不是私有方法。如果您将实例化代码作为私有方法隐藏起来,那么它将不具有优雅的可测试性。