我正在尝试使用Scalatest为我的java应用程序编写一些测试代码。我想,由于Scala具有更可读的语法,因此可以获得更易读的测试代码。
到目前为止,这是我管理的内容:
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 securityServiceMock = mock[SecurityService] val tag = new CheckRoleTag() tag.setSecurityService(securityServiceMock) tag.setGroup("group") tag.setPortal("portal") tag.setRoot(false) tag.setRole(null) tag.doStartTag should be(Tag.SKIP_BODY) } }
我对这段代码感到非常失望。实际上,我需要用Java编写它。请帮助我使它更像scala和功能。
答案 0 :(得分:9)
你无法通过重写测试来修复丑陋的测试。您只能通过重新设计正在测试的API来修复它。
嗯,从技术上讲, 可能会为优秀的API编写丑陋的测试,如果您尝试真的很难,非常邪恶,非常,愚蠢,非常醉或非常累。但写一个丑陋的测试需要努力并且程序员很懒惰,所以有人不太可能通过选择编写丑陋的测试。写丑陋的测试几乎是不可能的:你坚持下去,你得到一些东西,你检查你是否得到了你所期望的。而已。那里真的没有什么可以搞的。
测试只是使用API的方式与API的用户使用API的方式相同。它基本上是一个如何正确使用API的示例,几乎作为副作用,恰好检查API是否实际实现。这就是为什么丑陋的测试是错误的API设计的良好指标,这也是为什么测试驱动API设计是一件好事,即使你不做TDD也是如此。
在这种特殊情况下,我可以看到很多方法来改进API,虽然这些建议必然是不完整的,浅薄的和简单化的(更不用说可能是错误的),因为我对你的域名一无所知: / p>
setRoot
听起来像是在设置根目录。但是,除非false
是层次结构的根,否则我认为实际设置的内容是此标记是否为根。因此,它应该命名为isRoot
或makeRoot
或setIsRoot
或类似名称。setRoot
,假设我的猜测是正确的并且设置标记是否是根,那么默认是错误的方法。根据“root”概念的定义,只能有一个根。因此,您强制用户每次都指定setRoot(false)
,但实际定义根目录时一个时间除外。非根标记应该是默认标记,只应强制setRoot(true)
为一个标记实际 根目录。setRole(null)
。真的吗?您是强制用户明确设置角色取消设置?为什么不简单地取消默认设置?毕竟,测试被称为“...既没有角色也没有定义根”,为什么要定义它们呢?这样,测试基本上变成了:
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)
}
}
答案 1 :(得分:3)
下面的代码创建了新的匿名类,但doStartTag
按预期返回结果:
...
(new CheckRoleTag{
setSecurityService(mock[SecurityService])
setGroup("group")
setPortal("portal")
setRoot(false)
setRole(null)
} doStartTag) should be(Tag.SKIP_BODY)
...
答案 2 :(得分:3)
由于这个特定的测试只是在java中实现的对象上调用一堆setter,所以你可以做很多事情来使它更简洁,更实用或更具功能性。你可以用
之类的东西删除一些重复it should "allow access when neither role nor root defined" in {
val securityServiceMock = mock[SecurityService]
val tag = new CheckRoleTag()
locally {
import tag._
setSecurityService(securityServiceMock)
setGroup("group")
setPortal("portal")
setRoot(false)
setRole(null)
}
tag.doStartTag should be(Tag.SKIP_BODY)
}
在这种情况下,我不确定它是否真的值得。