Question

I have some code that uses the transaction sychronisation manager.. but i cannot seem to get it work in mocks.. im mocking the entity manager and transaction manager.. so that my context save an entity and call commit... the TransactionSynchronizationManager does not seem to get hit... in the test?

   this.transactionTemplate.execute(new TransactionCallback<E>() {
                @Override
                public E doInTransaction(TransactionStatus status) {    
                    // update entities


                    TransactionSynchronizationManager.registerSynchronization(new NotificationTransactionSynchronization(){
                       @Override
                       public void afterCommit() {
                    // do some post commit work
                                   int i = notifier.notifyAllListeners();
                       }
                    });

                }
            });

my test class:

@Test
public void testHappyPath() {


    context.checking(new Expectations() {
        {
            allowing(platformTransactionManager).getTransaction(definition);
            will((returnValue(status)));

            oneOf(platformTransactionManager).commit(status);

                         //next line never gets hit... so the test fails...
                         //if i remove it will pass but i need to check that it works...

            oneOf(mockNotifier).notifyAllListeners();

        }
    });
    this.TestClass.process();
    context.assertIsSatisfied();            
}   
Was it helpful?

Solution 2

I'm not sure I understand, but if you have a mock transaction manager, then who would be calling the notifier?

OTHER TIPS

Recently I got to the point where I had to test code which was using transactional hooks and after some investigation I got to following solution:

src:

public void methodWithTransactionalHooks() {

    //...

    TransactionSynchronizationManager.registerSynchronization(
        new TransactionSynchronizationAdapter() {
            public void afterCommit() { 
                // perform after commit synchronization
            }
        }
    );

    //...
}

test:

@Transactional
@Test
public void testMethodWithTransactionalHooks() {

    // prepare test

    // fire transaction synchronizations explicitly
    for(TransactionSynchronization transactionSynchronization 
        : TransactionSynchronizationManager.getSynchronizations()
    ){
        transactionSynchornization.afterCommit();
    }

    // verify results
}

Test by default is set to rollback so afterCommit synchronizations won't be fired. To test it, explicit call is necessary.

I ran into the same issue, in my case adding

@Rollback(false)

to the test method helped.

See https://stackoverflow.com/a/9817815/1099376

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top