Grails测试工厂类

Grails测试工厂类,grails,testing,integration-testing,Grails,Testing,Integration Testing,鉴于我是grails的新手,我正在尝试测试一个工厂类。工厂类位于src文件夹中,因为我不希望它作为服务 class UserFactory { static Map userDefaults = [ email : 'usermail@test.it', alias : 'myalias', firstName : 'Antonio', lastName : 'Ro

鉴于我是grails的新手,我正在尝试测试一个工厂类。工厂类位于src文件夹中,因为我不希望它作为服务

class UserFactory {

static Map userDefaults = [
        email           : 'usermail@test.it',
        alias           : 'myalias',
        firstName       : 'Antonio',
        lastName        : 'Roma',
        password        : 'asdhjs',
        placeOfBirth    : 'Milan',
        placeOfResidence: 'Berlin',
        dateOfBirth     : new Date() - 4000
]

static User build(Map properties, Map options = [persisted: true]) {
    userDefaults.putAll properties
    def user = new User(userDefaults)

    if (options.persisted) { user.save() }

    return user
}

static Collection<User> build(Collection<Map> properties, Map options = [persisted: true]) {
    properties.collect { build(it, options) }
}

你一开始就这么高调:

我想测试用户是否通过 戈姆。这里是集成测试:

@TestMixin(DomainClassUnitTestMixin)
class UserFactoryIntegrationSpec extends Specification {

def setup() {
    mockDomain(User)
}

def cleanup() {
}

void "create user"() {
    when:
    User user = UserFactory.build([alias: 'xx', email: 'xx@gmail.com'])

    then:
    User.count() == 1
    user.alias == 'xx'
    user.email == 'xx@gmail.com'
    user.id != null
}

void "create users"() {
    when:
    Collection<User> users = UserFactory.build([[alias: 'xx', email: 'xx@gmail.com'], [alias: 'yy', email: 'yy@gmail.com']])

    then:
    users.size() == 2
    users.alias == ['xx', 'yy']
    users.email == ['xx@gmail.com','yy@gmail.com']
    users.id != [null, null]
}
但后来一切都变得一团糟,因为你在使用一个单元测试假装是一个集成测试,更糟糕的是,你在用单元测试测试持久性

一定要使用集成测试来测试持久性。只有当单元测试对您正在测试的内容有意义,并且您希望强制域层以某种方式响应,以便您可以专注于正在测试的控制器/服务/等时,才使用域类模拟

使用集成测试,该测试至少配置一个H2数据库,具有完整的ACID支持、行锁定、真正的SQL查询等。如果您愿意,可以将其切换到测试Oracle模式、MySQL数据库等。但是您的测试运行真正的查询和更新。如果您使用mock来测试持久性,那么您实际上只是在测试mock

集成测试不使用mixin、mock等。有真正的Spring应用程序上下文、Hibernate(或您正在使用的任何GORM)、加载插件等。使用JUnit3(扩展
GroovyTestCase
)或JUnit4(无基类,使用JUnit注释)或Spock。请注意,集成测试将每个测试运行配置为在事务中进行,并在成功测试结束时回滚,或者在测试失败时回滚,但在这两种情况下,测试之间都没有结转


如果您想使用Spock(您应该这样做),那么扩展
grails.test.Spock.IntegrationSpec
,以获得默认为Spock测试的较新版本的grails。在旧版本中,安装spock插件并使用插件的集成基类。

将构建选项放入静态映射是一条毁灭之路。你将一块一块地销毁地图(每次调用),并且你有一个比赛条件!检查
save()
调用的结果,如果结果为false,则必须查看
user.errors
。或者,您可以事先将
failOnErrors:true
传递给save调用或
validate()
用户。谢谢@cfrick!我没有注意到。。。我已经修好了!
User.count() == 1
     |       |
     0       false

users.id != [null, null]
|     |  |
|     |  false
|     [null, null]
[rigel.resources.User : (unsaved), rigel.resources.User : (unsaved)]