Reputation: 865
I am using Grails 2.4.4 and want to apply spock tests in my project.
Below is the 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:
@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("[email protected]", "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=[[email protected]]
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 "[email protected]" in database? 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.
Upvotes: 0
Views: 1298
Reputation: 2312
In your test you're testing MemberService
, which means you don't need to mock it. Just refer to it via 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. You have it in your @Mock
annotation, which is good.
Now, create the object, preferably in a given
block:
void "test something"() {
given:
new Member(loginEmail: '[email protected]', password: '123456', ...).save(failOnError: true, flush: true)
when:
println "service is ${service}"
def result = service.login("[email protected]", "123456")
println "result is ${result}"
then:
result == MemberService.LoginResult.SUCCESS
}
I added failOnError: true
to make sure the object has actually been created. 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.
Also, you need to ensure the Member
object is initialized in a way that fulfills the path you want to reach. For example, if you want to reach LoginResult.SUCCES
state, you need to set member.isLocked
to false
, etc.
When you get this test to work, you may want to take a look into Build Test Data Plugin. It makes creating test data - like your Member
object - much easier.
Upvotes: 2