Grails 3 upgrade Test issues - grails

When I run tests with the Build-Test-Data plugin in grails 3 I see the following error.
groovy.lang.MissingMethodException: No signature of method: com...Item.save() is applicable for argument types: () values: [] Possible solutions: last(), wait(), any(), saveAll([Ljava.lang.Object;), saveAll(java.lang.Iterable), last(java.lang.String)
This is typically around a .save() or a .build() I am not a test guru so anyone know what is up?
Update
The example looks like this...
import grails.buildtestdata.mixin.Build
#Build(Author)
class AuthorUnitTests {
void testAuthorStuff() {
def author = Author.build()
...
}
}
My Code looks like...
#TestFor(Item)
#Build([Item])
class ItemSpec extends Specification
{
...
def "Blah Blah"() {
given:
Item i = Item.build(id: 1)
}
}

Below unit test passes in Grails 3.1.1:
package com.example
import grails.test.mixin.TestFor
import spock.lang.Specification
import grails.buildtestdata.mixin.Build
#TestFor(Item)
#Build(Item)
class ItemSpec extends Specification {
void "test something"() {
expect:
Item.build(name: 'Test').name == 'Test'
}
}
build.gradle
compile 'org.grails.plugins:build-test-data:3.0.0'
Make sure to build/compile the app once the plugin GAV added to build.gradle:
gradlew build
should do.

Related

Grails 3.3.8 : Unable to resolve ControllerUnitTest

I am attempting to write some basic controller tests and am following the documentation https://docs.grails.org/latest/guide/testing.html. My test currently is unable to find ControllerUnitTest. Is there a dependency that I am missing?
Here is my import
grails.testing.web.controllers.ControllerUnitTest
See the project at https://github.com/jeffbrown/mcroteaucontrollertest.
https://github.com/jeffbrown/mcroteaucontrollertest/blob/master/src/test/groovy/mcroteaucontrollertest/DemoControllerSpec.groovy
package mcroteaucontrollertest
import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification
import static org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED
class DemoControllerSpec extends Specification implements ControllerUnitTest<DemoController> {
void "test GET request"() {
when:
controller.index()
then:
response.text == 'Success'
}
void "test POST request"() {
when:
request.method = 'POST'
controller.index()
then:
response.status == METHOD_NOT_ALLOWED.value()
}
}
The ControllerUnitTest trait is provided by grails-web-testing-support. Make sure you have something like testCompile "org.grails:grails-web-testing-support" as shown at https://github.com/jeffbrown/mcroteaucontrollertest/blob/cf5f09b1c2efaba759f6513301d7b55fcb29979b/build.gradle#L56.

How to mock service in groovy/src class under test with Grails 3.3.x

I've recently upgraded to grails 3.3.1 and realised that grails.test.mixin.Mock has been pulled to separate project which has been build just for backward compatibility according to my understanding org.grails:grails-test-mixins:3.3.0.
I've been using #Mock annotation to mock Grails service injected into groovy/src class under test. What is the tactic to mock collaborating services in this case? Is there anything from Spock what I can use or should I fallback to grails-test-mixins plugin?
Class under test:
import gra
ils.util.Holders
import grails.util.Holders
class SomeUtilClass {
static MyService myService = Holders.grailsApplication.mainContext.getBean("myService")
static String myMethod() {
// here is some code
return myService.myServiceMethod()
}
}
My test spec (Grails 3.2.1):
import grails.test.mixin.Mock
import spock.lang.Specification
#Mock([MyService])
class ValidatorUtilsTest extends Specification {
def 'my test'() {
when:
def result = SomeUtilClass.myMethod()
then:
result == "result"
}
}
Due to you use Holders.grailsApplication in your SomeUtilClass, you can try to add #Integration annotation:
import grails.testing.mixin.integration.Integration
import spock.lang.Specification
#Integration
class ValidatorUtilsTest extends Specification {
def 'my test'() {
when:
def result = SomeUtilClass.myMethod()
then:
result == "result"
}
}
Not sure, but hope it work for you.
Try with this code
#TestMixin(GrailsUnitTestMixin)
#Mock([your domains here])
class ValidatorUtilsTest extends Specification {
static doWithSpring = {
myService(MyService)
}
def 'my test'() {
when:
def result = SomeUtilClass.myMethod()
then:
result == "result"
}
}
Remove the #Mock annotation and implement ServiceUnitTest<MyService> in your test class.

Inheritance in Grails Spock Integration Test

I have a few tests that are very similar in my Grails integration test suite (which uses Spock). I want to have a base test class which has the 90% of the common logic of the tests and then let test classes extend from it.
I was thinking:
public abstract BaseSpecification extends IntegrationSpec {
public baseTest() {
//
setUp:
//
...
when:
//
...
then:
...
}
}
and then:
public class SpecificTestSpecification extends BaseSpecification {
public baseTest() {
setup:
// more set up
super.baseTest();
when:
// some more specific testing
then:
// som more testing
}
}
But trying this I get two issues:
It runs both BaseClass and SpecificationClass
When the SpecificationClass runs, it fails on:
groovy.lang.MissingMethodException: No signature of method: BaseSpecification.baseTest() is applicable for argument types: () values: []
Possible solutions: any(), old(java.lang.Object), any(groovy.lang.Closure), notify(), wait(), Spy()
at
Any ideas how I can achieve inheritance in my spock integration tests?
I don't know if it can be done with Spock. When I tried I couln't find a way to reuse spock statements and what I did was to write a BaseSpecification class with utility methods that can be used inside spock statements.
This is an example test.
#TestFor(Address)
class AddressSpec extends BaseSpecification {
...
void "Country code should be 3 chars length"(){
when:
domain.countryCode = countryCode
then:
validateField('countryCode', isValid, 'minSize.notmet')
where:
[countryCode, isValid] << getMinSizeParams(3)
}
And the BaseSpecification class
class BaseSpecification extends Specification {
// Return params that can be asigned in `where` statement
def getMinSizeParams(Integer size){[
[RandomStringUtils.randomAlphabetic(size - 1), false],
[RandomStringUtils.randomAlphabetic(size), true]
]}
// Make an assetion, so it can be used inside `then` statement
protected void validateField(String field, String code, Boolean shouldBeValid){
domain.validate([field])
if(shouldBeValid)
assert domain.errors[field]?.code != code
else
assert domain.errors[field]?.code == code
}
}
It's an unit test but I think it should work with Integration tests too.
Okay, now I got your point.
You can pretty much use like this:
class BaseSpecification extends IntegrationSpec {
//User userInstance
def setup() {
// do your common stuff here like initialize a common user which is used everywhere
}
def cleanup() {
}
}
class SpecificTestSpecification extends BaseSpecification {
def setup() {
// specific setup here. Will call the super setup automatically
}
def cleanup() {
}
void "test something now"() {
// You can use that userInstance from super class here if defined.
}
}

Integration test - how to test a method with no inputs and a render

How does one integration-test (Grails) a controller with no inputs and a render view? Here is my controller code and test; the test looks correct but throws a "java.lang.Exception: No tests found matching grails test target pattern filter" error. many thanks for your help. -ryan
Controller code section:
class ReportSiteErrorsController {
static allowedMethods = [reportError: 'GET', saveReportError: 'POST']
def mailService
#Transactional(readOnly = true)
def reportError() {
render(view:'reportError', model:[])
}
}
Integration Test:
#TestFor(ReportSiteErrorsController)
class ReportSiteErrorsControllerTests extends DbunitGroovyTestCase {
#Test
void "test report error"() {
controller.reportError()
assert view == "reportError"
}
}
Leave the extension off in your command line. You are supposed to be specifying the name of the test, not the name of the file in which it is defined.
Use something like...
grails test-app integration: NameOfTest
Not something like...
grails test-app integration: NameOfTest.groovy
I hope that helps.
in Grails 2.4 the default syntax to test render "hello" would be:
import grails.test.mixin.TestFor
import spock.lang.Specification
/**
* See the API for {#link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
*/
#TestFor(SimpleController)
class SimpleControllerSpec extends Specification {
def setup() {
}
def cleanup() {
}
void "test something"() {
controller.index()
expect:
response.text == "hello"
}
}
The assert won't do for me. See also: the Grails Documentation

Grails java.io.File mocking

Is there any way to mock a file for unit testing in Grails?
I need to test file size and file type and it would help if I could mock these.
Any link to a resource would help.
You can mock java.io.File in Groovy code with Spock.
Here's an example of how to do it:
import spock.lang.Specification
class FileSpySpec extends Specification {
def 'file spy example' () {
given:
def mockFile = Mock(File)
GroovySpy(File, global: true, useObjenesis: true)
when:
def file = new File('testdir', 'testfile')
file.delete()
then :
1 * new File('testdir','testfile') >> { mockFile }
1 * mockFile.delete()
}
}
The idea is to return the file's Spock mock from a java.io.File constructor call expectation which has the expected parameters.

Resources