2017-09-18 5 views
0

Je fais des tests en utilisant Spock dans Grails 3. Un cas de test particulier se casse parce que Grails parle à ma base de données dans deux sessions différentes dans ce cas. Ma spécification est annotée avec @Rollback, pour annuler toutes les modifications apportées à chaque test.Comment éviter @Rollback dans une méthode spécifique?

Y at-il un moyen de désactiver @Rollback pour cette méthode unique, puis, une fois le test terminé, annulez manuellement les modifications?

Mise à jour

Un dépouillé exemple de mon spec test est ci-dessous:

@Log4j 
@Integration 
@Rollback 
class PublicationReportBreakingSpec extends Specification { 

    @Unroll 
    @Rollback 
    void "Invalidate #type object and check not in report"(type, status, hits, expect) 
    { 
     //We want to roll back the changes made to the publication after each pass. 

     given: "Find a valid #type publication" 
     //Finding publication which is Read (valid, should appear in report) 
     final Publication pub = getSinglePub(type, status, hits) 

     //Set publication to be Unread (invalid, shouldn't appear in report) 
     when: "The #type publication is altered to fail" 
     pub.setStatus('Unread') 
     pub.save(flush:true, failOnError: true) 

     then: "Check the properties match the test case" 
     pub.status = 'Unread' 

     //Generate report of read publications 
     when: "The report is run" 
     def resp = PublicationController.reportReadPublications() 

     //Make sure report doesn't contain the publication 
     then: "Check for expected result #expect" 
     checkReportExpectedResult(resp, expect) 

     where: 
     clause           | type  | status | hits || expect 
     "Book is unread"         | 'Book'  | 'Read' | 1200 || 0 
     "Article is unread"        | 'Article' | 'Read' | 200 || 0 
    } 

    //Checks report for expect value 
    public void checkReportExpectedResult(resp, expect){...} 

    //Returns single publication based on passed in parameters 
    public Publication getSinglePub(type, status){...} 
} 

Le stacktrace de l'erreur est:

<testcase name="Testing breaking domain class changes. Book is unread" classname="com.my.project.PublicationReportBreakingSpec" time="118.216"> 
<failure message="java.lang.IllegalStateException: No transactionManager was specified. Using @Transactional or @Rollback requires a valid configured transaction manager. If you are running in a unit test ensure the test has been properly configured and that you run the test suite not an individual test method." type="java.lang.IllegalStateException">java.lang.IllegalStateException: No transactionManager was specified. Using @Transactional or @Rollback requires a valid configured transaction manager. If you are running in a unit test ensure the test has been properly configured and that you run the test suite not an individual test method. 
at grails.transaction.GrailsTransactionTemplate.&lt;init&gt;(GrailsTransactionTemplate.groovy:60) 
at com.my.project.PublicationReportBreakingSpec (Removed due to sensitivity) 
at com.my.project.PublicationReportBreakingSpec (Removed due to sensitivity) 
at groovy.lang.Closure.call(Closure.java:414) 
at groovy.lang.Closure.call(Closure.java:430) 
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96) 
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) 
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93) 
at com.my.project.PublicationReportBreakingSpec.Invalidate #type object and check not in report. Check #clause, publication type #type(PublicationReportBreakingSpec.groovy) 

+0

Vous ne pouvez pas annuler un test Geb standard. Vous n'êtes pas en contrôle de la transaction depuis son passe sur un autre thread –

+0

D'accord, cela a du sens. Donc utiliser @Rollback est redondant, même s'il compile? Comment alors ferais-je mon test? Je modifie un objet de domaine et l'enregistre dans la base de données, mais il semble qu'une autre session exécute le scénario de test, ce qui provoque son échec et ne récupère pas les modifications enregistrées dans l'objet. Je fais '.save (flush: true)' sur les changements que je fais. – Donglecow

+0

Edité OP: Désolé, je viens de remarquer une faute de frappe dans le message. J'utilise Spock pas Geb pour tester. – Donglecow

Répondre

1

Selon le Javadoc annotant le test avec @Rollback(false) devrait faire l'affaire.

+0

J'ai essayé cela, en utilisant l'annotation sur cette méthode spécifique et j'obtiens une exception 'groovy.lang.MissingPropertyException: Aucune propriété de ce type: valeur pour la classe: org.grails.transaction.GrailsTransactionAttribute'. J'ai aussi essayé '@Rollback (value = false)' qui entraîne la même erreur. – Donglecow

+0

Pourriez-vous partager votre code et la pile complète –

+0

J'ai ajouté un exemple de mon code et de la pile. Il est fortement modifié en raison de la sensibilité, mais je crois que j'ai capturé les parties les plus importantes. – Donglecow

1

Il pourrait être un problème si @Rollback(false) ne fonctionne pas ...

Pour contourner ce problème, l'annotation peut être mis au niveau de la méthode aussi. Supprimez donc l'annotation de votre classe de test et placez-la sur vos méthodes de test, à l'exception de celle que vous ne souhaitez pas restaurer. Ajoutez ensuite une section cleanup: dans cette spécification pour nettoyer les données que vous avez créées.

0

Si vous ne souhaitez pas annuler vos modifications, vous ne souhaitez pas utiliser de transaction ... vous pouvez donc ignorer la transaction dans cette méthode. Vous pouvez le faire en utilisant @NotTransactional.