约束验证失败后内存中的对象无效

时间:2012-02-15 19:07:20

标签: hibernate unit-testing grails gorm

使用Grails 2.0.0我创建了服务,它创建了Player类的实例并将其保存在数据库中。然后我编写了JUnit集成测试,检查服务方法createNewPlayer(String platformID)如果在Player.save中的约束验证失败时抛出异常(failOnError:true)。

一切顺利,但如果我打电话,方法应该失败(...):

assert Player.list().size() == 1;

我收到此错误:

--Output from testCreatingNewPlayerWithExistingID--
| Error 2012-02-15 21:52:05,293 [main] ERROR hibernate.AssertionFailure  - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
Message: null id in test1.Player entry (don't flush the Session after an exception occurs)

我的问题是:如何在shouldFail方法中测试抛出异常,以便在此之后Hibernate不会在内存中保留带有null id的Player类的无效实例?

在我的代码示例下面:

class WorkingService
{
    Player createNewPlayer(String platformID) throws ValidationException {
        Player player = new Player(platformID: platformID);
        return player.save(failOnError : true);
    }
}


class Player
{
    String platformID
    static constraints = {
        platformID nullable: false, blank: false, unique: true
    }
}


@TestFor(WorkingService)
class WorkingServiceTests
{
    WorkingService workingService;

    void testCreatingNewPlayerWithExistingID()
    {
        def player = new Player(platformID: "1");
        player.save(flush: true);

        assert Player.list().size() == 1;

        shouldFail ValidationException, {
            player = workingService.createNewPlayer("1");
        }

        assert Player.list().size() == 1;
    }
}

1 个答案:

答案 0 :(得分:1)

我认为问题在于您正在混合集成测试和单元测试。集成测试应该扩展GroovyTestCase而不使用像TestFor这样的AST转换注释。这传递给我的测试应用程序:

import grails.validation.ValidationException

class WorkingServiceTests extends GroovyTestCase {

   WorkingService workingService

   void testCreatingNewPlayerWithExistingID() {

      new Player(platformID: "1").save(flush: true)

      assert Player.count() == 1

      shouldFail(ValidationException) {
         workingService.createNewPlayer("1")
      }

      assert Player.count() == 1
   }
}

不相关 - 您不应该使用list().size()从数据库中获取计数,因为它只是为了获取数字而加载每个实例;请改用count()。另外nullable: false是默认值,因此指定它是多余的。