2011-04-12 104 views
6

我正在Java中实现一个模型,它需要对集合进行迭代并经历多个标识阶段,它涉及到循环,while循环等。这是我想要的东西在细粒度级别进行测试,以便我相信它已正确实施。单元测试,静态和工厂

我已经使用它作为开始单元测试的机会,因为它是我认识到有益于我的代码的东西。自那以后,我一直在阅读丛书,以加快JUnit和单元测试的速度。

基本上我的问题可以归结为两个相互矛盾的建议件我收到:

1)静是邪恶的。不要碰静电。不要测试私人,你可能想要在那里上课。
2)使用工厂创建允许使用参数进行依赖注入 - 可能允许使用模拟和存根进行隔离。

在我的例子我期待执行沿行的操作:

double height = 223.42; // this was set iterating over a collection of doubles 
//blah 
HeightBounds b = HeightBounds.getHeightBounds(height); 
//more blah 

为了避免建立什么将成为一个非常漫长而复杂的代码块,我已经这样做了,我只能整体测试。通过这种方式,我可以测试公共可访问对象,以确保系统组件全部正确执行。

常识对我说,静态工厂没有错,而且他们很容易测试,但是我错过了一些盲目明显的东西,因为我正在学习测试驱动设计?

谢谢

+1

你应该单元测试每种测试有意义的方法,这包括静态方法。 – DwB 2011-04-12 15:17:27

+2

“statics is evil”有可能主要针对静态_variables_,因为它们在测试之间保留它们的值,因此如果测试没有正确重置,可能会导致测试之间的依赖关系。在我看来,不接触静态变量的静态_methods_没有问题。 – 2011-04-12 15:19:59

+0

问题是我可以在类中作为静态方法调用来进行边界检查,但它会非常程序化,我不想将它列在公共接口中。我可以在不改变可见性的情况下测试静态方法的一种方法是扩展类以进行测试并制作方法来调用它们,但是我读到的所有内容都是“静态方法是代码味道”,您应该使用类。鉴于我在嵌入式环境中运行,尽管我更喜欢避免创建对象的想法,而不是完美的OO设计......仍在审议! – Uniqe 2011-04-12 15:26:05

回答

3

静态工厂类会在类和HeightBounds类之间引入耦合。这可能会使你的课难以测试,例如HeightBounds关闭并在DB中查找信息,或者从Web服务等读取。

如果你改为将IHeightBounds实现注入到类中,那么你可以嘲笑所以你可以测试当你的类的依赖做某些事情时会发生什么。

例如,如果HeightBounds引发异常会怎么样?或返回null?或者你想测试什么时候返回一个特定的HeightBound?使用界面很容易嘲笑这种行为,对于静态工厂来说,由于您制作数据以在课堂上创建理想的结果,因此更加困难。

您仍然只能使用HeightBounds的单个实现,并且能够独立测试,但即使没有真正的实现,您也可以测试上述方法。

我可能会有一个IHeightBoundFactory接口并向类中注入一个实现。

至于测试私处,一般你不想。你想要测试2件事中的一件,或者结果是你所期望的,或者是你所期望的相互作用。

如果你有一个名为Add方法与一个叫GetAll,那么你可能想测试,当你调用Add,然后调用GetAll你回来,你添加的一种方法。你不在乎这是如何实现的,而是它的工作原理。这是测试结果。通常在这种情况下,您希望创建返回数据的模拟对象。这似乎是你的情况。

如果您在调用Add时希望记录正在添加的内容,那么您需要测试与日志记录依赖关系的交互,以便注入模拟依赖关系并验证当您调用Add时与该类的交互发生了。通常在这种情况下,您希望创建具有预期设置的模拟对象,并验证是否满足这些期望。它看起来不是这样,在你上面描述的情况下是必要的。

+0

不是我想做自己的代表,但你可以,一般来说,在接受答案之前要等待,因为更多的人可能有机会发表他们的意见,或者将我的观点拍下来:) – 2011-04-12 15:35:54

+0

好的,谢谢,会按照你的建议做,并等待进一步的反馈,并完成解决其他答案(这也涵盖了很多好的内容)。 – Uniqe 2011-04-12 15:39:50

+0

我认为这是答案,因为你能够发现我想要达到的目标以及我误解的概念,然后举出例子填补空白。谢谢 – Uniqe 2011-04-15 08:12:04

2

静是邪恶的。不要碰静电。

这里的“静态”可能意味着单身,即全局状态。这在单元测试中确实很难使用,并且会引入很多细微的问题,所以最好避免它。然而,static成员(字段,方法或内部类)通常不一定是本身的问题。

不要测试私人,你可能需要一个班。

如果你觉得需要测试一个私有方法,这是一个迹象表明你的API没有足够精细,并且封装类可能会尝试做太多,这是真的。通常你可以确定一些连贯的功能组合,这可以更好地提取到一个单独的类中。这可以改善您的设计,从而使单元测试更加轻松。

1

静态方法基本上杀死了单元测试。

当你想单元测试你的应用程序的基本思想之一是能够隔离你的代码的不同部分。您通常通过为您的环境布线模拟对象来实现此目的。如果使用静态方法,则不能连线任何东西。而且,使用静态方法隐藏对象之间的依赖关系。

在你最后一段你说你想学习测试驱动设计。如果你在之后编写你的测试你已经编写了你的​​代码,你的测试并没有真正驱动任何东西。先写测试。

关于私有方法,您通常会对使用这些私有方法的公共方法进行全面测试,因此无论如何您都要覆盖它们。如果你有一个非常复杂的私人方法,你想测试(你不应该)只是使用反射来使其可访问。我宁愿打破封装而不是未经测试的代码。

Misko Hevery在这个话题上有一个非常的nice post

+0

DistanceBounds本身并不存在 - 我仍然在充分考虑如何测试它们,从而充实了需要什么对象以及该过程。也许TDD并不是我的意思,但基本上,而不是瀑布式的定义我所有的测试/代码,我期待写它们,因为我一次编写代码,方法......当然,测试正在驱动我的设计,但是,也许这不是TDD或任何正式的过程。 – Uniqe 2011-04-12 15:53:17

2

静态工厂的一个问题是,您无法通过模拟替换工厂(以及某些时候由工厂创建的对象)。 - 这是IOC Containers如此有用的原因之一。

+0

谢谢,IoC容器是一个非常好的关键字谷歌,我一直在阅读本:http://martinfowler.com/articles/injection.html – Uniqe 2011-04-14 10:24:35

0

静态方法本身并不是邪恶的。看看JDK中有多少人在那里。静态方法也需要进行单元测试,所以如果你有任何进行和测试。

所以静态方法杀死单元测试并不是真的。

但是,如果您只是在单元测试中编写较少的代码,那么这是一个错误的路径,因为正如其他人所说,您应该更好地使用您的对象使用通常的API - 因为这是你想测试。

首先编写测试的完整ACK - 它也将帮助您设计更好的API,正确地削减您的课程。

+1

人们说静态方法杀死单元测试的原因不是因为你不能测试静态方法,而是调用静态方法的代码很难单独测试。在Java的情况下,你必须使用支持字节码工具的框架(如JMockit)来模拟/伪造/存根/ w/e方法。据我了解,这并不理想(尽管我最近才了解这种可能性)。 – 2012-11-04 15:27:38

+0

其实我个人不知道有人这么说,所以不能评论“人说”。对我来说,“杀死单元测试”听起来像“现在你有静态方法,你真的很麻烦,不能单元测试”,这显然不正确(正如我所说的)。诚然,这使得测试更加困难,但并非不可能。有时候静态方法是有益的。一旦你有他们,你应该测试他们。就像你说的是嘲笑其中一种可能性,我会说很好。其他的是准备国家,以便测试工作 - 我做了不止一次,这绝对有可能。 – 2012-11-14 11:06:05

+0

我认为你的陈述“所以静态方法杀死单元测试是不对的。”是对相反的回应。我评论的原因是因为我觉得你的答案是“静态方法可以使用,因为你也可以测试它们”,我想补充我所理解的缺点:嘲笑它们很困难,因为它更复杂,也比正常嘲笑。一般来说,你希望你的单元测试是简单的(所以你可以维护它们)和快速(所以你可以经常运行它们)。 – 2012-11-14 13:40:14