如何使用 Spock 测试 Grails 服务?
Posted
技术标签:
【中文标题】如何使用 Spock 测试 Grails 服务?【英文标题】:How to test Grails service using Spock? 【发布时间】:2013-09-09 18:36:11 【问题描述】:我有一个EncouragementService.groovy
,方法如下
class EncouragementService
def stripePaymentService
def encourageUsers(List<User> users)
if(null != users && users.size()>0)
for(User user : users)
//logic
stripePaymentService.encourage(user)
//
要在 JAVA 世界中测试上面的代码,我会首先使用 JUnit 在 setup 中创建两个或三个用户。将用户列表传递给encourageUsers(...)
方法并检查我想要的结果。
如何在 grails 中实现同样的目标,
import com.github.jmkgreen.morphia.Datastore;
@TestFor(EncouragementService)
class EncouragementServiceSpec
def morphiaService = new MorphiaService()
void testEncourageUsers()
List<User> users = createUsers();
encouragementService.(users)
//
def createUsers()
Datastore datastore = morphiaService.dataStoreInstance()
def user = new User()
user.setName("Prayag Upd")
//
datastore.save(user)
[user]
我正在使用spock:0.7
plugins
test(":spock:0.7") exclude "spock-grails-support"
【问题讨论】:
【参考方案1】:服务类可以优化如下:
class EncouragementService
def encourageUsers(List<User> users)
if(users) //Groovy truth takes care of all the checks
for(user in users)
//logic
Spock 单元测试: Spock 将测试提升到另一个层次,您可以在其中测试行为(遵守 BDD)。测试类看起来像:
import spock.lang.*
@TestFor(EncouragementService)
@Mock(User) //If you are accessing User domain object.
class EncouragementServiceSpec extends Specification
//def encouragementService //DO NOT NEED: mocked in @TestFor annotation
void "test Encourage Users are properly handled"()
given: "List of Users"
List<User> users = createUsers()
when: "service is called"
//"service" represents the grails service you are testing for
service.encourageUsers(users)
then: "Expect something to happen"
//Assertion goes here
private def createUsers()
return users //List<User>
【讨论】:
“耐心”是my name,我不是在开玩笑;)。坦率地说,最近我在本地 Grails 用户组的 spock 上有一个 presentation,所以我想我会吹嘘我所做的一些事情。 ;) @SérgioMichels @dmahapatro 当User
不是基于grails-app/domain
的实体时,我得到Failure: test Users are properly handled(np.zazzercode.service.EncouragementServiceSpec) | org.codehaus.groovy.grails.exceptions.GrailsConfigurationException: Cannot add Domain class [class np.zazzercode.domain.User]. It is not a Domain! at grails.test.mixin.domain.DomainClassUnitTestMixin.registerGrailsDomainClass(DomainClassUnitTestMixin.groovy:209)
@PrayagUpd 是的,如果 User 不是域类,那么您将不需要 @Mock
这就是我在答案中的意思。
@dmahapatro 好的,但是我如何初始化在EncouragementService
中使用的服务(例如stripePaymentService
)。由于没有注入,因此在测试应用程序时抛出 java.lang.NullPointerException: Cannot invoke method encourage() on null object
@dmahapatro 好吧,将def stripePaymentService = Mock(StripePaymentService) service.stripePaymentService = stripePaymentService
添加到given
已修复【参考方案2】:
使用build-test-data plugin 建立用户。
@TestFor(EncouragementService)
@Build(User)
class EncouragementServiceSpec extends Specification
def "encourage users does x"()
given:
def users = createUsers();
when:
service.encourageUsers(users)
then:
// assert something
def createUsers()
[User.build(), User.build(), User.build()]
我还对代码进行了一些更改,以使其成为正确的 spock 规范。您的测试必须扩展规范,您可能想熟悉Spock's keywords。
【讨论】:
build-test-data plugin 看起来很棒,但似乎不适用于非基于grails-app/domain
的实体。抛出异常org.codehaus.groovy.grails.exceptions.GrailsConfigurationException: Cannot add Domain class [class np.zazzercode.domain.User]. It is not a Domain
以上是关于如何使用 Spock 测试 Grails 服务?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spock 控制器测试中模拟 Grails 请求对象方法
使用 Spock 进行 Grails 测试 - 选择哪个模拟框架?
IntelliJ IDEA 的零覆盖:带有 Spock 单元测试的 Grails
Grails / Spock:如何在类中模拟从类本身调用方法的单个方法?
在 Intellij Idea 中运行 grails 2.1.3 测试:Spock 测试中出现奇怪错误:无法添加域类 [class x.y.Z]。它不是域