[英]How to use spock to test a service with real transactions in Grails application?
I am using Grails 2.4.4 and want to apply spock tests in my project. 我正在使用Grails 2.4.4,并想在我的项目中应用spock测试。
Below is the MemberService : 以下是MemberService :
@Transactional
class MemberService {
def lastMember = null
def login (userId, password) {
def member = Member.findByLoginEmail(userId)
if(!member) return LoginResult.NO_SUCH_MEMBER
if (member.isLocked) return LoginResult.MEMBER_IS_LOCKED
log.debug("member.password is [${member.passwd}], input password is [${password}]")
if (!member.passwd.equals(password)) return LoginResult.PASSWORD_ERROR
switch(member.validateResult) {
case "FAILED":
return LoginResult.VAILDATE_FAILED
case "WAIT":
return LoginResult.WAIT_VALIDATE
}
member.lasLoginTime = new Timestamp(System.currentTimeMillis())
member.lastLoginPlatform = "WEB"
member.loginFailCount = 0
member.save()
lastMember = member
return LoginResult.SUCCESS
}
enum LoginResult {
SUCCESS,
NO_SUCH_MEMBER,
PASSWORD_ERROR,
MEMBER_IS_LOCKED,
VAILDATE_FAILED,
WAIT_VALIDATE
}
enum ValidateResult {
SUCCESS,
FAILED,
WAIT
}
}
MemberServiceSpec is as below: MemberServiceSpec如下:
@TestFor(MemberService)
@Mock(Member)
class MemberServiceSpec extends Specification {
def memberService
def setup() {
memberService = new MemberService()
}
void "test something"() {
when:
println "service is ${service}"
def result = memberService.login("aa@mymail.com", "123456")
println "result is ${result}"
then:
result == MemberService.LoginResult.SUCCESS
}
}
The test result is as below: 测试结果如下:
Testing started at 15:15 ...
|Loading Grails 2.4.4
|Configuring classpath
.
|Environment set to test
....................................
|Running without daemon...
..........................................
|Compiling 1 source files
.
|Running 2 unit tests...|Running 2 unit tests... 1 of 2
--Output from test something--
1. setup
service is cusine_market.MemberService@54c425b1
Enter MemberService.login----------------userId=[aa@mymail.com]
result is NO_SUCH_MEMBER
Failure: |
test something(cusine_market.MemberServiceSpec)
|
Condition not satisfied:
result == MemberService.LoginResult.SUCCESS
| |
| false
NO_SUCH_MEMBER
at cusine_market.MemberServiceSpec.test something(MemberServiceSpec.groovy:32)
Condition not satisfied:
result == MemberService.LoginResult.SUCCESS
| |
| false
NO_SUCH_MEMBER
Condition not satisfied:
result == MemberService.LoginResult.SUCCESS
| |
| false
NO_SUCH_MEMBER
at cusine_market.MemberServiceSpec.test something(MemberServiceSpec.groovy:32)
|Completed 1 unit test, 1 failed in 0m 6s
.Tests FAILED
I confirm that the user exists in database. 我确认该用户存在于数据库中。
Could anyone tell me why MemberService can not find the user "aa@mymail.com" in database? 谁能告诉我为什么MemberService在数据库中找不到用户“ aa@mymail.com”? I also tried the below line
我也尝试了以下行
memberService = Mock(MemberService);
The result is the same. 结果是一样的。 However, if I run-app, the service does find the user.
但是,如果我运行应用程序,则该服务会找到用户。
In your test you're testing MemberService
, which means you don't need to mock it . 在测试中,您正在测试
MemberService
,这意味着您无需对其进行模拟 。 Just refer to it via service
. 只需通过
service
引用即可。
This looks like unit test, not the integration one. 这看起来像单元测试,而不是集成测试。 So it doesn't use your database at all.
因此,它根本不使用您的数据库。
What you need to do is to create the Member
instance manually in test. 您需要做的是在测试中手动创建
Member
实例。 You have it in your @Mock
annotation, which is good. 您可以在
@Mock
批注中添加它,这很好。
Now, create the object, preferably in a given
block: 现在,最好在
given
块中创建对象:
void "test something"() {
given:
new Member(loginEmail: 'aa@mymail.com', password: '123456', ...).save(failOnError: true, flush: true)
when:
println "service is ${service}"
def result = service.login("aa@mymail.com", "123456")
println "result is ${result}"
then:
result == MemberService.LoginResult.SUCCESS
}
I added failOnError: true
to make sure the object has actually been created. 我添加了
failOnError: true
以确保实际上已创建对象。 You - of course - need to provide all required properties in Member
constructor and make sure the data you provide correspond to the one you provide to login
method. 您-当然-需要在
Member
构造函数中提供所有必需的属性,并确保您提供的数据与您提供给login
方法的数据相对应。
Also, you need to ensure the Member
object is initialized in a way that fulfills the path you want to reach. 另外,您需要确保以满足您要到达的路径的方式初始化
Member
对象。 For example, if you want to reach LoginResult.SUCCES
state, you need to set member.isLocked
to false
, etc. 例如,如果要达到
LoginResult.SUCCES
状态,则需要将member.isLocked
设置为false
,等等。
When you get this test to work, you may want to take a look into Build Test Data Plugin . 当您使该测试生效时,您可能想看看Build Test Data Plugin 。 It makes creating test data - like your
Member
object - much easier. 它使创建测试数据(如您的
Member
对象)更加容易。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.