Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails Spock unit test requires to mock transaction manager

In Grails 3.1.12, I want to unit test a service:

@Transactional
class PlanService {
    List<Plan> getPlans(Map params) {
        def currentUser = (User)springSecurityService.getCurrentUser()
        return Plan.findAllByCompany(currentUser.employer, params)
    }
}

Like this:

@TestFor(PlanService)
@Mock([Plan, User, Company])
class PlanServiceSpec extends Specification {
    void "Retrieve plan from the current user"() {
        setup:
        // create and save entities here

        when: "the plans are retrieved"
        def params = null
        def plans = service.getPlans(params)

        then: "the result should only include plans associated to the current user's company"
        plans.size() == 2
}

Running the test from the console:

grails> test-app my.PlanServiceSpec -unit

Fails with:

my.FundingPlanServiceSpec > Retrieve plan from the current user FAILED
java.lang.IllegalStateException at PlanServiceSpec.groovy:48

and in the test report (HTML):

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.

Now if I comment out the @Transactional annotation in the service, the test passes, but that's not the intended implementation. I am able to work around the problem by mocking the transaction manager:

service.transactionManager = Mock(PlatformTransactionManager) {
    getTransaction(_) >> Mock(TransactionStatus)
}

But this seems very awkward, if not wrong.

Is there some incantation I forgot to invoke?

EDIT: looks similar to an old bug, but it's been closed more than a year.

like image 260
youri Avatar asked Oct 03 '16 12:10

youri


People also ask

What is the Grails testing support framework?

Since Grails 3.3, the Grails Testing Support Framework is used for all unit tests. This support provides a set of traits. An example hello world test can be seen below: For more information on writing tests with Grails Testing Support see the dedicated documentation.

Can Spock verify the Order in which mock methods are called?

And in addition to verifying the mock method calls we specify, we can verify no other extra methods are called on our mock objects: Spock also provides the ability to verify the order in which mock methods are called by specifying the order in multiple ‘then’ blocks:

What is the best way to do unit testing with Spock?

Spock makes it easy by combining these features as a part of the framework itself with a more readable groovy syntax along with the lesser boilerplate code. Mocks, Stubs, and Spies are used extensively in unit testing for increasing coverage and testing or validating the core business logic of the application under test.

What is the Spock mocking framework?

The Spock testing framework includes powerful mocking capabilities that work well in unit tests. The Spock documentation is extensive, but I often find myself hunting for the syntax of the different mocking mechanisms in Spock.


2 Answers

Have you tried what a comments says that fixes the problem? If not, try to annotate the test class with:

@TestMixin(DomainClassUnitTestMixin)

and then:

service.transactionManager = getTransactionManager()
like image 162
Fran García Avatar answered Oct 28 '22 10:10

Fran García


Was getting the same error in grails 3.3.2 when trying to test transactional service.

adding DataTest interface solved the issue for me.

class HelloServiceSpec extends Specification implements ServiceUnitTest<HelloService>, DataTest { }

like image 34
argoden Avatar answered Oct 28 '22 11:10

argoden