Grails 3 Integration Spec has Strange Transactional Behavior -
i have following test (which more of functional test integration but...):
@integration(applicationclass = application) @rollback class conventioncontrollerintegrationspec extends specification { restbuilder rest = new restbuilder() string url def setup() { url = "http://localhost:${serverport}/api/admin/organizations/${organization.first().id}/conventions" } def cleanup() { } void "test update convention"() { given: convention convention = convention.first() when: restresponse response = rest.put("${url}/${convention.id}") { contenttype "application/json" json { name = "new name" } } then: response.status == httpstatus.ok.value() convention.findbyname("new name").id == convention.id convention.findbyname("new name").name == "new name" } }
the data being loaded via bootstrap (which admittadly might issue) problem when i'm in then
block; finds convention
new name , id
matches, when testing name
field, failing because still has old name.
while reading documentation on testing think problem lies in session data gets created in. since @rollback
has session separate bootstrap
, data isn't gelling. example, if load data via test's given
block, data doesn't exist when controller called restbuilder
.
it entirely possible shouldn't doing kind of test way, suggestions appreciated.
this functional test - you're making http requests against server, not making method calls , making assertions effects of calls.
you can't automatic rollbacks functional tests because calls made in 1 thread , they're handled in another, whether test runs in same jvm server or not. code in bootstrap runs once before of tests run , gets committed (either because made changes in transaction or via autocommit), , 'client' test code runs in own new hibernate session , in transaction testing infrastructure starts (and roll @ end of test method), , server-side code runs in own hibernate session (because of osiv) , depending on whether controller(s) , service(s) transactional or not, may run in different transaction, or may autocommit.
one thing not factor here should considered hibernate persistence tests session caching. hibernate session first-level cache, , dynamic finder findbyname
trigger flush, want, should explicit in tests. won't clear cached elements , run risk of false positives code because might not loading new instance - hibernate might returning cached instance. when calling get()
. add flushandclear()
method integration , functional base classes , i'd put call after put
call in when
block sure flushed hibernate database (not committed, flushed) , clear session force real reloading. pick random domain class , use withsession
, e.g.
protected void flushandclear() { foo.withsession { session -> session.flush() session.clear() } }
since put
happens in 1 thread/session/tx , finders run in own, shouldn't have effect should pattern used in general.
Comments
Post a Comment