In Grails 3.2.x and earlier I could do something like this in a spock unit test:
def myServiceMock = Mock(MyService) {
someMethod() >> 42
}
Closure doWithSpring() {{ ->
myService(InstanceFactoryBean, myServiceMock, MyService)
}}
def "some test"(){
expect:
service.myService.someMethod() == 42
}
This would enable the mock to be injected in collaborating classes.
See: http://docs.grails.org/3.2.4/guide/testing.html
Under the "doWithSpring and doWithConfig callback methods, FreshRuntime annotation" section.
In Grails 3.3.2 it does not seem to work anymore.
And the mention of it has been removed from the testing documentation.
Is there any way to accomplished that behaviour again?
Many thanks in advance!
/brian
Grails 3.3 comes with new testing framework.
Here you can find docs - https://testing.grails.org/latest/guide/index.html
To run test on grails 3.3. you can modify your code in this way:
def myServiceMock = Mock(MyService) {
someMethod() >> 42
}
def setup() {
defineBeans{
myService(InstanceFactoryBean, myServiceMock, MyService)
}
}
Related
I am trying to run my unit tests in Grails 4.0.3 through the command grails test-app.
Unfortunately I am in trouble with dependency injection.
I have basically two test cases. The first one does not work with the response No GORM implementations configured. Ensure GORM has been initialized correctly It seems that PidService is not correctly injected.
To demonstrate my suspicion I created a private method which only throws an exception, to be invoked in the second test case. So, I invoked that method in the second one and it worked as expected. The exception was correctly catched and I could verify that the message is correct.
package br.gov.cmb.pid.tests
import br.gov.cmb.pid.services.PidService
import grails.testing.services.ServiceUnitTest
import org.grails.web.json.JSONObject
import spock.lang.Specification
class PidIssuingSpec extends Specification implements ServiceUnitTest<PidService> {
def setup() {
}
def cleanup() {
}
def "Test that injection is not working"() {
given:
JSONObject wrongPidIssuingDocument = new JSONObject()
when:
service.buildPidIssuingOrder(wrongPidIssuingDocument)
then:
def e = thrown(Exception)
e.message == "Register number is mandatory."
}
def "Test that works because no injection is necessary"(){
when:
dispException()
then:
def e = thrown(Exception)
e.message == "Register number is mandatory."
println(e.message)
}
private void dispException(){
throw new Exception("Register number is mandatory.")
}
}
Grails Unit Test does not work when dependency inject is necessary
In general unit tests that require dependency injection is supported.
See the Modifying the Application Context section at https://testing.grails.org/2.4.1/guide/index.html#unitTesting. That demonstrates how to add beans to the context in a unit test so they may be injected. For example, you could do this:
Closure doWithSpring() {{ ->
// create a bean named "someService" which
// is an instance of SomeService.
// the someService bean may be injected into the
// the class under test
someService(SomeService)
}}
At https://github.com/grails/grails-testing-support/blob/9f782ff3b911919e421440feb8a2e4736c6aced6/examples/demo33/src/test/groovy/demo/ReportingServiceSpec.groovy is a working example:
package demo
import grails.testing.services.ServiceUnitTest
import spock.lang.Specification
class ReportingServiceSpec extends Specification implements ServiceUnitTest<ReportingService> {
Closure doWithSpring() {{ ->
someHelper RushHelper
}}
void "test dependency injection"() {
expect:
service.retrieveSomeNumber() == 2112
}
}
class RushHelper implements MathHelper {
#Override
int getSomeNumber() {
2112
}
}
Notice that the service being tested is the ReportingService. The RushHelper is being injected into that service to support the test.
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.
Okay, I have a custom taglib inside a custom taglib like so:
def preference = { attrs, body ->
def sliderTaglib = grailsApplication.mainContext.getBean('com.myCustom.sliderTagLib')
sliderTaglib.slider.call(attrs, body)
}
Since I am using grailsApplication.mainContext.getBean() , how do i mock that in my unit test? My test complains:
grails Error executing tag No bean named is defined...
I've tried various methods to mock it but to no avail. It functions correctly when I run-app though, it's just the test that fails. I'm using grails 2.3.9 and spock. :(
My test looks like this:
void "taglib should output a slider"() {
when:
def result = applyTemplate("""
<a:preference class='slider'/>
""")
then:
result == "<div class='slider'></div>"
}
You can mock the taglib by using
#TestMixin(GroovyPageUnitTestMixin)
class MultipleTagLibSpec extends Specification {
void "test multiple tags"() {
given:
mockTagLib(sliderTagLib)
expect:
// …
}
}
By the you should must not lookup the sliderTagLib bean in the application context. You simple call the taglib by calling the taglib-namespace.taglib-method.
E.g. the Grails taglibs are in the g namespace. Therefore use it like this.
def preference = { attrs, body ->
out << g.link(...)
// in your case
yourNamespace.slider(....)
}
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.
I have a grails 2.1 app which has a controller that calls a method on a service, passing in a request and a response:
class FooController {
def myService
def anAction() {
response.setContentType('text/xml')
myservice.service(request,response)
}
I want to unit test this method. And I want to do so using GMock (version 0.8.0), so this is what I tried:
def testAnAction() {
controller.myService = mock() {
service(request,response).returns(true)
}
play {
assertTrue controller.anAction()
}
}
Now this fails saying that that it failed expectations for request.
Missing property expectation for 'request' on 'Mock for MyService'
However, if I write my test like this:
def testAnAction() {
def mockService = mock()
mockService.service(request,response).returns(true)
controller.myService = mockService
play {
assertTrue controller.anAction()
}
}
The test will pass fine. As far as I am aware they are both valid uses of the GMock syntax, so why does the first one fail and the second one not?
Cheers,
I assume you write your tests in a test class FooControllerTest generated by grails.
In a such way, FooControllerTest class is annoted by #TestFor(FooController) wich inject some usefull attributes.
So request is an attribute of your test class, not a variable in the local scope.
It's why it is not reachable from a internal Closure.
I'm convinced that following code could work (I have not tested yet) :
def testAnAction() {
def currentRequest = request
def currentResponse = response
controller.myService = mock() {
service(currentRequest,currentResponse).returns(true)
}
play {
assertTrue controller.anAction()
}
}