在运行时,此代码有效:

// Service class
class UserService {
    ApiClient api

    User create(User user) throws EmailTakenException, UsernameTakenException {
        User savedUser

        try {
            savedUser = api.users.create user
            setEnabled savedUser.id, true
            return savedUser
        }
        catch(ApiException ex) {
            switch(ex.subStatus) {
                case SubStatus.USERS_EMAIL_TAKEN:
                    throw new EmailTakenException()
                    break
                case SubStatus.USERS_USERNAME_TAKEN:
                    throw new UsernameTakenException()
                    break
            }
        }
    }
}

从 Controller 调用:
// Controller class, an action
def create(CreateCommand cmd) {
    if(request.get) {
        render view: 'create'
        return
    }

    if(!cmd.validate()) {
        flash.model = cmd
        redirect action: 'create'
        return
    }

    def user = new User()
    bindData user, params

    try {
        userService.create user

        flash.success = 'ui.save.success'
    }
    catch(EmailTakenException ex) {
        flash.model = cmd
        flash.error = 'ui.email.taken'
    }
    catch(UsernameTakenException ex) {
        flash.model = cmd
        flash.error = 'ui.username.taken'
    }

    redirect action: 'create'
}

“User”,“SubStatus”和“ApiException”类来自jar库依赖项。发生错误时,ApiClient会引发ApiException。

在运行时,此代码可完美运行,但是当我为此编写规范时,它将引发UndeclaredThrowableException。这是Spock规范:
ApiClient api
UsersApi apiUsers

void setup() {
    api = Mock()
    apiUsers = Mock()
    api.users >> apiUsers

    service.api = api
}

def "create: it should be able to throw an exception when email is already taken"() {
    setup:
    def user = new User(email: '[email protected]', username: 'foo', name: 'Bar Foo')
    def exception = Mock(ApiException)
    exception.subStatus >> SubStatus.USERS_EMAIL_TAKEN

    when:
    service.create user

    then:
    thrown(EmailTakenException) // GrailsException is runtime
    1 * apiUsers.create(_ as User) >> { throw new ApiException(400, SubStatus.USERS_EMAIL_TAKEN, null) }
}

最佳答案

也许您可以使用@FailsWith批注重写测试?
http://code.google.com/p/spock/wiki/SpockBasics#Extensions

10-04 10:12