2009-06-17 69 views
3

所以我有,看起来像一个辅助方法如下:我需要测试助手/设置方法吗?

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); 

回答

1

首先,该方法是私人的,所以通常我会说测试可能不是直接用于该方法所必需的。即使它是真实代码的辅助方法,而不是您的测试的助手,您可能只想通过公共接口间接测试它。第二,如果你确实想测试它 - 也许无论如何 - 你应该考虑使用工厂来创建对象,而不是直接实例化对象。使用工厂,并结合接口,将允许您将依赖关系抽象出来。只需将工厂注入包含此方法的类的构造函数中,并将其用作此方法内的属性即可创建适当的对象。如果你走这条路线,你也可能会发现工厂也是创建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(); 
} 
3

要回答你的第一个问题,是你应该测试这种方法。测试这种方法比编写整篇文章要少得多,并且会为您提供运输代码验证。

在这方面取决于你打算做的方法。假设函数的合理行为如下:

  • 如果我为第一个参数传递null,会发生什么?
  • 如果我传递第二个参数的负数,会发生什么?
  • 在您期望的情况下,GetInstanceOfD会实际返回一个D吗?
  • D是否具有给定输入的正确值。
  • 如果C,A和B实例假设可以访问,那么情况如何?
+0

一般来说,我的私有方法是由于重构使代码保持DRY或方法很小而产生的。在这种情况下,代码实际上可能已经在重构之前通过现有测试进行了测试。在这种情况下,我通常不会直接为此方法编写测试,而是依赖现有测试和任何新的公共方法测试。情况并非总是如此,我对使用反射/访问器测试的私有方法进行了一些测试,但通常情况下,我只测试公共接口,因此我的测试不会不必要地耦合到类的内部。 – tvanfosson 2009-06-17 03:10:50

2

当你遇到这样的问题时,要记住的一件好事是让事情琐碎

设置方法需要微不足道。拆解方法需要微不足道。帮助者方法可以是非常平凡的 - 如果他们有自己的一套测试。

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

0

private方法通常是一个指标,他们并不需要,因为你将要测试使用这些private方法的方法来直接测试。

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

1

您应该测试此方法。你应该测试它,因为它可能会失败;一个XP谚语是测试一切可能打破

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

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

//--- don't write this, you'll probably regret it ;o) 
D d = new (new C(new A(), new B(), "string"), 1024);