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.
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.
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:
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.
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.
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()
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 {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With