您无法通过重写测试来修复丑陋的测试。您只能通过重新设计正在测试的 API 来修复它。
好吧,从技术上讲,如果你真的很努力,很邪恶,很愚蠢,很醉或很累,就有可能为好的 API 编写丑陋的测试。但是编写丑陋的测试需要付出努力,而且程序员很懒惰,因此不太可能有人会选择编写丑陋的测试。编写丑陋的测试几乎是不可能的:你插入一些东西,你取出一些东西,你检查你是否得到了你期望的东西。就是这样。那里真的没有什么可丑化的。
测试使用 API 的方式与 API 用户使用它的方式相同。它基本上是一个如何正确使用 API 的示例,几乎作为副作用,碰巧检查了 API 是否正确实现。这就是为什么一个丑陋的测试是糟糕的 API 设计的一个很好的指标,这也是为什么测试驱动 API 设计是一件好事,即使你不做 TDD。
在这种特殊情况下,我可以看到很多改进 API 的方法,尽管这些建议必然是不完整的、肤浅的和简单化的(更不用说可能是错误的),因为我对您的领域一无所知:
- 更好的名字:
setRoot
听起来像是在设置根。但是,除非false
是你的层次结构的根,否则我假设它实际设置的是这个标签是否是根。所以,它应该被命名为isRoot
or makeRoot
orsetIsRoot
或类似的东西。
- 更好的默认值:继续
setRoot
,假设我的猜测是正确的并且这设置了标签是否是根,那么默认值是错误的。根据“根”概念的定义,永远只能有一个根。所以,你强迫你的用户每次都指定setRoot(false)
一次,除了他们实际定义根的那一次。非根标签应该是默认设置,您应该只强制setRoot(true)
使用那个实际上是根标签的标签。
- 更好的默认值,第二部分:
setRole(null)
。严重地?您是在强迫您的用户明确将角色设置为未设置?为什么不简单地将 unset 设为默认值?毕竟,测试被称为“......当既没有定义角色也没有定义根”,那么为什么要定义它们呢?
- Fluent API / Builder Pattern:如果你真的必须构造无效对象(但请参阅下一点),至少使用 Fluent API 或 Builder Pattern 之类的东西。
- 仅构造有效对象:但实际上,对象在构造时应该始终是有效的、完整的和完全配置的。您不必构造一个对象,然后对其进行配置。
这样,测试基本上变成了:
package com.xyz
import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers
import com.xyz.SecurityService
import org.mockito.Mockito._
import org.scalatest.mock.MockitoSugar
import org.mockito.Matchers._
import javax.servlet.jsp.tagext.Tag
class CheckRoleTagSpec extends FlatSpec with ShouldMatchers with MockitoSugar {
behavior of "CheckRole tag"
it should "allow access when neither role nor root defined" in {
val tag = new CheckRoleTag(mock[SecurityService], "group", "portal")
tag.doStartTag should be(Tag.SKIP_BODY)
}
}