Grails里DOMAIN类的一对一,一对多,多对多关系总结及集成测试

简介: 终于干完这一章节,收获很多啊。 和DJANGO有类似,也有不同。 User.groovy: package com.grailsinaction class User { String loginId String password Date dat...

终于干完这一章节,收获很多啊。

和DJANGO有类似,也有不同。

User.groovy:

package com.grailsinaction

class User {

    String loginId
    String password
    Date dateCreated

    static hasOne = [profile: Profile]
    static hasMany = [posts: Post, tags: Tag, following: User]
    static mapping = {posts sort: 'dateCreated'}

    static constraints = {
      loginId size: 3..20, unique: true, nullable: false
      password size: 6..8, nullable:false, validator: { passwd, user -> passwd != user.loginId }
      profile nullable: true
    }
}

Profile.groovy:

package com.grailsinaction

class Profile {
        User user
        byte[] photo
        String fullName
        String bio
        String homepage
        String email
        String timezone
        String country
        String jabberAddress
        
    static constraints = {
            fullName blank: false
            bio nullable: true, maxSize: 1000
            homepage url:true, nullable: true
            email email: true, blank: false
            photo nullable:true, maxSize: 2 * 1024 * 1024
            country nullable: true
            timezone nullable: true
            jabberAddress email: true, nullable: true
    }
}

Post.groovy:

package com.grailsinaction

class Post {
        String content
        Date dateCreated

    static constraints = {
            content blank: false
    }
        
        static belongsTo = [user: User]
        static hasMany = [tags: Tag]
        
        static mapping = { sort dateCreated: "desc"}
}

Tag.groovy:

package com.grailsinaction

class Tag {
        String name
        User user

    static constraints = {
            name blank: false
    }
        
        static hasMany = [posts: Post]
        static belongsTo = [User, Post]
}

UserIntegrationSpec.groovy:

package com.grailsinaction


import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*

@Integration
@Rollback
class UserIntegrationSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    def "Saving our first user to the database"() {
            given: "A brand new user"
            def joe = new User(loginId: 'Joe', password: 'secret')
            when: "the user is saved"
            joe.save()
            
            then: "it saved successfully and can be found in the database"
            joe.errors.errorCount == 0
            joe.id != null
            User.get(joe.id).loginId == joe.loginId
        }
        
        def "Updating a saved user changes its properties"() {
            given: "An existing user"
            def existingUser = new User(loginId: 'Joe', password: 'secret')
            existingUser.save(failOnError: true)
            when: "A property is changed"
            def foundUser = User.get(existingUser.id)
            foundUser.password = 'sesame'
            foundUser.save(failOnError: true)
            
            then: "The change is reflected in the database"
            User.get(existingUser.id).password == 'sesame'
        }
        
        def "Deleting an existing user removes it from the database"() {
            given: "An existing user"
            def user = new User(loginId: 'Joe', password: 'secret')
            user.save(failOnError: true)
            
            when: "The user is deleted"
            def foundUser = User.get(user.id)
            foundUser.delete(flush: true)
            
            then: "The user is removed from the database"
            !User.exists(foundUser.id)
        }
        
        def "Saving a user with invalid properties causes an error"() {
            given: "A user which fails several field validations"
            def user = new User(loginId: 'Joe', password: 'tiny')
            when: "The user is validated"
            user.validate()
            
            then:
            user.hasErrors()
            
            "size.toosmall" == user.errors.getFieldError("password").code
            "tiny" == user.errors.getFieldError("password").rejectedValue
            !user.errors.getFieldError("loginId")
        }
        
        def "Recovering from a failed save by fixing invalid properties"() {
            given: "A user that has invalid properties"
            def chuck = new User(loginId: 'chuck', password: 'tiny')
            assert chuck.save() == null
            assert chuck.hasErrors()
            
            when: "We fix the invalid properties"
            chuck.password = "fistfist"
            chuck.validate()
            
            then: "The user saves and validates fine"
            !chuck.hasErrors()
            chuck.save()
        }
        
        def "Ensure a user can follow other users"() {
            given: "A set of baseline users"
            def joe = new User(loginId: 'joe', password: 'password').save()
            def jane = new User(loginId: 'jane', password: 'password').save()
            def jill = new User(loginId: 'jill', password: 'password').save()
            
            when: "Joe follows Jan & Jill, and Jill follows Jane"
            joe.addToFollowing(jane)
            joe.addToFollowing(jill)
            jill.addToFollowing(jane)
            
            then: "Follower counts should match follow people"
            2 == joe.following.size()
            1 == jill.following.size()
        }
        
}

PostIntegrationSpec.groovy:

package com.grailsinaction


import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*

@Integration
@Rollback
class PostIntegrationSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    def "Adding posts to user links post to user"() {
            given: "A brand new user"
            def user = new User(loginId: 'joe', password: 'secret')
            user.save(failOnError: true)
            
            when: "Several posts are added to the user"
            user.addToPosts(new Post(content: "First post.....w002!"))
            user.addToPosts(new Post(content: "Second post......"))
            user.addToPosts(new Post(content: "Third post...."))
            
            then: "The user has a list of posts attached"
            3 == User.get(user.id).posts.size()
        }
        
        def "Ensure posts linked to a user can be retrieved"() {
            given: "A user with several posts"
            def user = new User(loginId: 'joe', password: 'secret')
            user.addToPosts(new Post(content: "First"))
            user.addToPosts(new Post(content: "Second"))
            user.addToPosts(new Post(content: "Third"))
            user.save(failOnError: true)
            
            when: "The user is retrieved by their id"
            def foundUser = User.get(user.id)
            def sortedPostContent = foundUser.posts.collect {
                it.content
            }.sort()
            
            then: "The posts appear on the retrieved user "
            sortedPostContent == ['First', 'Second', 'Third']
        }
        
        def "Exercise tagging several post with various tags"() {
            given: "A user with a set of tags"
            def user = new User(loginId: 'joe', password: 'secret')
            def tagGroovy = new Tag(name:"groovy")
            def tagGrails = new Tag(name:"grails")
            user.addToTags(tagGroovy)
            user.addToTags(tagGrails)
            user.save(failOnError: true)
            
            when:"The user tags two fresh posts"
            def groovyPost = new Post(content: "A groovy post")
            user.addToPosts(groovyPost)
            groovyPost.addToTags(tagGroovy)
            
            def bothPost = new Post(content: "A groovy and grails post")
            user.addToPosts(bothPost)
            bothPost.addToTags(tagGroovy)
            bothPost.addToTags(tagGrails)
            
            then:
            user.tags*.name.sort() == ['grails', 'groovy']
            1 == groovyPost.tags.size()
            2 == bothPost.tags.size()
            
        }
}

目录
相关文章
|
29天前
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
20 1
|
1月前
|
Java
【Java每日一题】— —第二十一题:编程把现实生活的手机事物映射成一个标准类Phone,并定义一个测试类PhoneDemo测试Phone类的功能
【Java每日一题】— —第二十一题:编程把现实生活的手机事物映射成一个标准类Phone,并定义一个测试类PhoneDemo测试Phone类的功能
36 0
|
2月前
|
算法 测试技术 C++
【矩阵快速幂】封装类及测试用例及样例
【矩阵快速幂】封装类及测试用例及样例
|
4月前
|
测试技术
软件测试/测试开发|测试用例设计方法——等价类划分
软件测试/测试开发|测试用例设计方法——等价类划分
43 1
|
5月前
|
分布式计算 测试技术 API
为集成LLM到测试平台提供更便捷的方式:为讯飞的LLM星火创建接入LangChain类(全部源代码)
为集成LLM到测试平台提供更便捷的方式:为讯飞的LLM星火创建接入LangChain类(全部源代码)
316 0
对自己的“平均随机数封装类”的测试
对自己的“平均随机数封装类”的测试
|
1月前
|
Java
java面向对象高级分层实例_测试类(main方法所在的类)
java面向对象高级分层实例_测试类(main方法所在的类)
9 1
|
1月前
|
测试技术 Python
在Python中测试类
在Python中测试类
11 1
|
2月前
|
数据可视化 jenkins 测试技术
可视化BI类产品如何设计测试框架?
可视化BI类产品如何设计测试框架?
|
3月前
|
算法 测试技术 C#
【矩阵快速幂】封装类及测试用例及样例
【矩阵快速幂】封装类及测试用例及样例

热门文章

最新文章