So Ive got a Grails 3.2.3 app, and in one of the services, I am loading a WSDL located in the root of my project folder to use with a SOAPClient like so:
def wsdl = "soap.wsdl"
SOAPClient soapClient
#PostConstruct
void init() {
soapClient = new SOAPClient(wsdl)
}
My spock test is annotated with #MockFor(MyService) and Ive checked that the test runs the init method fine.
Now when the app is running, this creates the SOAPClient just fine, but when trying to write a Spock test, new SOAPClient(wsdl)returns null. Im guessing this is because when running the Spock test, the wsdl isnt properly in the classpath, but I havent found a way to solve this. Any ideas please?
If it were me, I would metaClass the constructor of SOAPClient to return a mock of SOAPClient. Something like this:
def 'test something'(){
setup:
def soapClientMock = Mock(SOAPClient)
SOAPClient.metaclass.constructor = {String filename ->
assert filename == "soap.wsdl"
return soapClientMock
}
}
Related
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.
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 {
}
I am new in Grails, I want to write unit tests for services using Spock. However I have the following issue.
import grails.transaction.Transactional
#Transactional
class BService {
boolean createB(){
return true
}
...
}
For this class I wrote the following test:
class BServiceTest extends Specification {
def "test createB"(){
given:
def service = new BService()
when:
def boolean temp
temp = service.createB()
then:
temp == true
}
}
The error I am getting when I run this test is the following:
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.
and it shows in GrailsTransactionTemplate.groovy:60
I would really appreciatie if anyone can give me a hint.
Add a #TestFor(BService) annotation to your unit test and use the instance of the service that it automatically provides. See http://grails.github.io/grails-doc/3.0.x/guide/testing.html for more information on testing.
Thank you ataylor for your reply. However I did a mistake, so I am now ansewring my own question.
First of all, the name conversion is wrong. When I create a service in grails there is automatically set a unit-test for this, so in that case I would have:
#TestFor(BService)
class BServiceSpec extends Specification {
def setup() {
User u = new User(1)
u.save()
}
def cleanup() {
}
def "test something"(){
}
}
In this case when I write a unit test, it runs.
The test that I had before was a functional test where I could not pass objects from the domain, so I had an error of the transactional manager.
I have used manually written as well as Grails generated Unit tests for this command object:
package myapp
#grails.validation.Validateable
class SearchCommand {
String basisBuild
String buildToSearch
static constraints = {
basisBuild(blank: false)
}
}
After having my hand written unit test fail I used Grails:
create-unit-test myapp.SearchCommand
I filled in the Unit Test, and made an assertion that should pass per documentation on mocked constraints:
package myapp
import static org.junit.Assert.*
import grails.test.mixin.*
import grails.test.mixin.support.*
import org.junit.*
#TestMixin(GrailsUnitTestMixin)
class SearchCommandTests {
void setUp() {
mockForConstraintsTests(SearchCommand)
}
void tearDown() {
// Tear down logic here
}
void testSomething() {
SearchCommand commandUnderTest = new SearchCommand()
commandUnderTest.validate(basisBuild: "")
assertEquals "blank", commandUnderTest.errors['basisBuild']
}
}
Why am I getting this failure?
grails> test-app
| Running 9 unit tests... 9 of 9
| Failure: testSomething(com.siemens.soarian.sf.gap.SearchCommandTests)
| java.lang.AssertionError: expected:<blank> but was:<null>
at org.junit.Assert.fail(Assert.java:93)
I believe I found the grails supported way to unit test Command objects in grails 2.0. You need to use mockCommandObject provided by the ControllerUnitTestMixin.
Credit to Erik
http://www.jworks.nl/2012/04/12/testing-command-objects-in-grails-2-0/
EDIT
Using validate() appropriately and mockForConstraintsTest should work if the patch mentioned in the existing Grails bug is in place (Thanks to #codelark for bringing that up). In order to test the command object from a Web App standpoint (using controller) the below information would be helpful.
Test Command Object Using Controller action:-
A command object is only deemed as such when it is used as a parameter in one of the action method inside a controller. Refer Command Objects (Warning NOTE).
Use SearchCommand in an action method, you should be able to assertEquals.
Sample:
void testSomething() {
YourController controller = mockController(YourController) //Or instantiate
SearchCommand commandUnderTest = new SearchCommand ()
//Note the usage here. validate() does not take parameters
commandUnderTest.basisBuild = ''
commandUnderTest.validate()
//Call your action
controller.searchCommandAction(commandUnderTest)
assert response.text == 'Returned'
assertEquals "blank", commandUnderTest.errors['basisBuild']
}
YourController's action:-
def searchCommandAction(SearchCommand sc){
render "Returned"
}
Note:
With out the patch from the grails bug we see the below error in #Grails 2.1.4, 2.2.0 & 2.2.1
I get an error when I only correct the validation and use mockForConstraintTests without using controller action:
You are using the validate method incorrectly. You never set the field on the class, so the field is null, not blank. Try changing your test as follows:
void testSomething() {
SearchCommand commandUnderTest = new SearchCommand()
commandUnderTest.basisBuild = ""
assertFalse commandUnderTest.validate()
assertEquals 'blank', commandUnderTest.errors['basisBuild']
}
Edit: There is also a grails bug when testing command classes that use the #Validatable annotation. There are some workarounds in the bug commentary.
When migrating from Grails 2.0.0 to 2.1.2 some of our tests started failing with NullPointerException (the same behavior is observed with Grails 2.0.3)
Here are snippets of code enough to reproduce the issue.
The controller:
class TestController {
def test() {
render(template: "/test")
}
}
The unit test:
import static org.junit.Assert.*
import grails.test.mixin.*
import grails.test.mixin.support.*
import org.junit.*
import grails.test.mixin.web.GroovyPageUnitTestMixin
#TestMixin(GroovyPageUnitTestMixin)
#TestFor(TestController)
class TestControllerTests {
void test_paramsAndSession_Null() {
controller.test()
def result = response.text
print result
assert render(template: "/test") == result
}
}
The template _test.gsp:
Params and session test.
Params(<%params.id1%>)<br/>
Session(<%session.id2%>)<br/>
With Grails 2.0.0 the application and the test work fine.
With Grails 2.1.2 the application still works fine, but the test starts failing with NullPointerException:
java.lang.NullPointerException: Cannot get property 'id1' on null object
at D__Eclipse_Workspace_paramsAndSessionTest_grails_app_views__test_gsp.run(_test.gsp:2)
at TestController.test(TestController.groovy:4)
at TestControllerTests.test_paramsAndSession_Null(TestControllerTests.groovy:12)
java.lang.NullPointerException: Cannot get property 'id2' on null object
at D__Eclipse_Workspace_paramsAndSessionTest_grails_app_views__test_gsp.run(_test.gsp:3)
at TestController.test(TestController.groovy:4)
at TestControllerTests.test_paramsAndSession_Null(TestControllerTests.groovy:12)
(The second exception appears when fix (1) below is applied)
What is the reason for that?
I see I can fix the test making the following changes:
params.id1 -> params?.id1 (1)
session.id2 -> session?.id2
But this does not look like a valid solution (changing my application for unit tests to work).
Please help me understand whether I am doing something wrong or there is a bug in Grails.
UPDATE: I've submitted a bug http://jira.grails.org/browse/GRAILS-9718
I've written a Grails tag that is just a very thin wrapper around the Grails select tag
package com.example
class MyTagLib {
def listTrees = {attrs ->
List<TreeDto> allTrees = getMandatoryAttributeValue(attrs, 'trees')
out << g.select(from: allTrees)
}
}
I've wrtitten a unit test for this class, but when I run it, I get the following error when the last line is executed:
groovy.lang.MissingMethodException: No
signature of method:
com.example.MyTagLib.select() is
applicable for argument types:
(java.util.LinkedHashMap)
It seems like the reference to the grails tags in the g namespace are not available when running unit tests. I've tried creating an integration test instead, but this doesn't work either.
Is there a way to test test a tag that calls another tag without stubbing/mocking the output of that other tag?
You have to mock the grails taglib you are using and inject it via the metaClass mechanism.
protected void setUp() {
super.setUp()
mockTagLib(FormTagLib)
def g = new FormTagLib()
tagLib.metaClass.g = g
}