2013-08-09 2 views
7

MySql을 사용하는 Rails 4.0 응용 프로그램에서는 rspec을 strategy : transaction으로 구성된 database_cleaner gem과 함께 사용하여 모든 테스트 케이스에 대해 데이터베이스를 정리합니다. 롤백해야하는 사용자 정의 트랜잭션이있는 경우 작동하지 않습니다. database_cleaner 보석 단지 표준 방법을 사용하지 않고rspec의 사용자 정의 트랜잭션이 작동하지 않습니다

:

config.use_transactional_fixtures = true 

모두는 aspected하게 작동합니다. 하지만 자바 스크립트로 기능 테스트를 실행하려면 fixture 삭제 전략을 truncation으로 변경하려면 database_cleaner가 필요합니다.

database_cleaner를 사용자 정의 트랜잭션과 함께 사용하려면 어떻게해야하며 표준 rspec 트랜잭션 전략과 다른 점은 무엇입니까?

+0

나는 DatabaseCleaner.strategy = : deletion/DatabaseCleaner.strategy = : truncation에 대해 알고 있다고 확신합니다. 나는 이것이 database_cleaner의 : 트랜잭션 전략 내에서의 문제인지 또는 이것이 예기치 않게 때때로 작동하는 중첩 된 트랜잭션과 관련된 일반적인 문제 일 경우에도 여전히 관심이 있습니다. –

답변

11

문제는 database_cleaner가 테스트 마지막에 ActiveRecord.rollback을 호출한다는 것인데, 이는 코드에서도 사용됩니다. InnoDB/MySQL은 진정한 중첩 된 트랜잭션을 지원하지 않으므로 코드에서 중첩 된 트랜잭션은 명시 적으로 그렇게 호출되지 않으면 트랜잭션으로 처리되지 않습니다.

합니다 (액티브 워드 프로세서에서)이 블록을 고려 :

User.transaction do 
    User.create(username: 'Kotori') 
    User.transaction do 
    User.create(username: 'Nemu') 
    raise ActiveRecord::Rollback 
    end 
end 

당신이 롤백 호출 후에 일어날 것으로 예상합니까? Nemu 사용자를 롤백하고 Kotori에 남겨 둘 예정입니까? 글쎄, 실제로 일어나는 것은 Kotori와 Nemu가 모두 만들어 졌다는 것입니다. 중첩 된 트랜잭션 (AR은 현재 상위에 대해 신경 써야 함) 및 상위 트랜잭션 (실제 db 트랜잭션)에 롤백 호출이 표시되지 않아서 롤백이 트리거되지 않습니다. 격리 된 블록. 이상해.

솔루션 :

Klass.transaction(requires_new: true) 

당신이 requires_new 설정하면, 액티브가 사용하거나 (포스트 그레스 위해 MySQL을/이노 것이 세이브 포인트를 만들 것입니다, 중첩 거래를 할 수 있습니다) 중첩 된 트랜잭션을 의사가-사용합니다. ActiveRecord를 사용하여 롤백을 호출하면 범위가 파악되고 적절한 롤백이 실행됩니다.

다른 해결책은 트랜잭션이 포함 된 테스트의 전략으로 잘라 내기 또는 삭제를 사용하는 것입니다.

+0

위대한 설명. 감사! –