Grails Spock unit test requires to mock transaction manager
Asked Answered
L

2

5

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.

Lens answered 3/10, 2016 at 12:12 Comment(0)
R
9

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()
Riffe answered 3/10, 2016 at 15:1 Comment(3)
I had completely overlooked that point. That's a nicer workaround. Thank you.Lens
I used this solution with grails 3.0.17 and the @TestMixin wasn't needed.Mushro
Helped me. Even for separately injected service. 2.4.5Alonzoaloof
R
3

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 { }

Resistencia answered 2/3, 2018 at 22:34 Comment(1)
Yes the above answer doesn't work for Grails 3.3.x (And I'm looking for an answer to that)Eyeopener

© 2022 - 2024 — McMap. All rights reserved.