We have a `BaseIntegrationTest` that most of our i...
# testing
d
We have a
BaseIntegrationTest
that most of our integrations tests extend so we don’t have to do the same setup for each one. We have an aroundEach in that
BaseIntegrationTest
which wraps each test in a transaction so we can rollback any database changes that each test did to prep for data for the test. That works great if the database transactions are in the actual
it()
test. But if we do a database action in the
beforeEach()
it is not rolling back the transaction and is committing instead. Any ideas on how to change this so the rollback works whether the database action occurs in the
it()
or the
beforeEach()
? (function in the thread)
t
I had a similar complaint, that I wanted to be able to do things around
describe
calls, so that in a given/when/then construct, I could prep data inside the givens. I didn't find a solution, and it also looks like I didn't file a feature request with TestBox either.
e
Currently not possible.
The lifecycle order is
before -> around -> after
You could manually set transaction points and restore perhaps?
But that seems 🤮
d
I suppose an alternative is I just have to put the database stuff in every test instead of in a
beforeEach()
? I could pull it all out into a
setupAllTheThings()
method to make that a little better in each test. Hmm.
@lmajano - you were looking for improvements as you’re digging into some Testbox development. An easy way to make this better would be great.
w
@danmurphy I had exactly the same problem last week. I generated some user in my beforeEach, which was polluting my database now with new users. It’s what Eric says, there’s this before -> around -> after lifecycle order. I had similar problems with aroundhanders in the base rest handler in coldbox which interfered with my own preHandler stuff. But in this test case I think you can create your own workaround. Because the transaction handling is in the aroundhandler, you should create your own which executes WITHIN the transaction block, e.g.
Copy code
/**
     * This function is tagged as an around each handler.  All the integration tests we build
     * will be automatically rolled backed. No database corruption
     *
     * @aroundEach
     */
    function wrapInTransaction( spec ) {
   
        transaction action="begin" {
            try {
                if ( structKeyExists( this, "someFunction") ) {
                    somefunction();
                }
                arguments.spec.body();
            } catch ( any e ) {
                rethrow;
            } finally {
                transaction action="rollback";
            }
        }
    }
So in this case you can put your own beforeEach in
someFunction
. I created some condition around it just to see if your ownfunction is there, or you could create a generic (or empyt) someFunction in your baseSpec. In your own spec you can define
someFunction
and do some specific db related stuff which is now part of your transaction. You could even execute some generic stuff AND spec specific code in the same method, e.g.
Copy code
function someFunction(){
  super.someFunction()
  // do my own thing
}
Word of warning: I did some very simple tests to see if this concept worked, and I believe it does, but no guarantees. Maybe the experts can tell me if I am missing something here. I think it is quite common people want to generate some db related stuff before each test and clean up automatically. If this concept works, it should not be too hard to translate it to something more generic.