I am trying to make use of {throw new Exception()} in Spock, but on running the test it prints in report--
"The following problems occurred:
Expected exception of type 'java.lang.Exception', but no exception was thrown"
package testing
import spock.lang.Specification
class MyFirstSpec extends Specification {
def "Test_One" (){
given:
def obj = new SpockMethodsPlaceholder()
obj.returnAge(0) >> {throw new Exception("invalidAge")}
when:
1*obj.returnAge(0)
then:
Exception ex = thrown()
ex.getMessage() == "invalidAge"
}
class SpockMethodsPlaceholder {
def "returnAge" (int age){
return age
}
}
}
Is there something wrong with my code?
Below is the stack trace of test run---
Working Directory:
Gradle User Home: /home/mafia/.gradle
Gradle Distribution: Gradle wrapper from target build
Gradle Version: 4.3
Java Home: /usr/lib/jvm/java-8-oracle
JVM Arguments: None
Program Arguments: None
Build Scans Enabled: false
Offline Mode Enabled: false
Tests: testing.MyFirstSpec
:compileJava UP-TO-DATE
:compileGroovy NO-SOURCE
:processResources NO-SOURCE
:classes UP-TO-DATE
:compileTestJava
:compileTestGroovy
:processTestResources NO-SOURCE
:testClasses
:test
testing.MyFirstSpec > Test_One FAILED
org.spockframework.runtime.WrongExceptionThrownError at MyFirstSpec.groovy:16
1 test completed, 1 failed
There were failing tests. See the report at: file:///media/mafia/A08200E98200C62E/Study/Git_Repo/GIT_JAVA/workbench/SpockProject/build/reports/tests/test/index.html
BUILD SUCCESSFUL in 19s
4 actionable tasks: 3 executed, 1 up-to-date
It looks like you misunderstand the concept of stubbing/mocking
What exactly is tested? Class SpockMethodPlaceholder? In this case it should not be mocked/ stubbed its a "class-under-test" - the code that you check and want to gain a confidence that it works (the code in the methods of this class if you wish)
On the other hand, if you use >> syntax you probably do intend to Stub something.
So here is a better example:
public class SomeClass {
public int return getAge(int age) {
if(age <= 0) {
throw new IllegalArgumentException("too young");
} else {
return age;
}
}
}
class SomeClassTest extends Specification {
def "an exception is thrown if the person is too young" () {
given:
def subject = new SomeClass()
when:
subject.getAge(-1)
then:
def ex = thrown(IllegalArgumentException)
ex.message == "too young"
}
}
Related
When do grails unit test with Spock, can't auto inject a service instance to domain.
Below is my code.
Service:
class HiService {
public HiService(){
println "Init HiService," + this.toString()
}
def sayHi(String name){
println "Hi, ${name}"
}
}
Domain:
class User {
public User(){
if (hiService == null){
println "hiService is null when new User(${name})"
}
}
String name
def hiService
def sayHi(){
println "Before use hiService " + hiService?.toString()
hiService.sayHi(name)
println "End use hiService" + hiService?.toString()
}
}
TestCase:
#TestFor(HiService)
#Mock([User])
class HiServiceTest extends Specification {
def "test sayHi"() {
given:
def item = new User( name: "kitty").save(validate: false)
when: "Use service method"
item.sayHi()
then : "expect something happen"
assertEquals(1, 1)
}
}
The following was console log:
--Output from test sayHi--
Init HiService,test.HiService#530f5e8e
hiService is null when new User(null)
Before use hiService null
| Failure: test sayHi(test.HiServiceTest)
| java.lang.NullPointerException: Cannot invoke method sayHi() on null object
at test.User.sayHi(User.groovy:17)
at test.HiServiceTest.test sayHi(HiServiceTest.groovy:20)
The service initialized, but can't inject to domain. But when run app directly, service will auto-inject to domain
If you wan't autowiring it needs to be an integration test. If using Grails 3 then annotate with #Integration, if grails 2 then extend IntegrationSpec.
See: http://docs.grails.org/latest/guide/testing.html#integrationTesting
#Mock([User, HiService])
class HiServiceTest extends Specification {
def "test sayHi"() {
// ....
}
}
Since you are writing unit tests, your service will not be autowired. Also as you are unit testing the User class object, you should write the test in UserSpec (instead of UserServceTest; Suffixing Spec is the convention in Spock). Now you can mock the HiService instead like this:
class UserSpec extends Specification {
def "User is able to say hi"() {
given:
User user = new User(name: 'bla bla')
and: "Mock the user service"
def hiService = Mock(HiService)
user.hiService = hiService
when:
user.sayHi()
then:
1 * sayHiService.sayHi(user.name)
}
}
I'm testing a Grails application but i get this error message:
I'm trying to do unit test. My Grails version is 2.4.3
Error executing script TestApp: java.lang.ClassNotFoundException: grails.plugin.spock.
That's my code:
#TestFor(TrackEmailController)
#Mock(TrackEmail)
class TrackEmailUnit2Spec extends Specification {
def setup() {
}
def cleanup() {
}
void "test something"() {
}
void 'test mandrillEventsEndPoint'() {
when:
controller.mandrillEventsEndPoint()
then:
response.text == 'mandrill Events End Point'
}
}
Can you be a little more specific on how you are running your test cases and how you have integrated spock dependencies? Or perhaps provide a github link to replicate the issue?
With grails 2.5.1, I only created a service with a simple property initialized through a constructor (#PostConstruct also)
Any unit test that read this property through a service method get a NullPointerException
Here's how to reproduce:
grails> create-app acme
grails> create-service DataService
acme/DataService.groovy
#Transactional
class DataService {
def data = null;
#PostConstruct
def setup() {
if (data == null) {
println("Initializing the service ...")
data = "<DATA>"
}
}
def serviceMethod() {
setup()
}
def getDataLength() {
println("Getting data length ...")
return data.length(); // Line 26
}
}
acme/DataServiceSpec.groovy
#TestFor(DataService)
class DataServiceSpec extends Specification {
def setup() {
}
def cleanup() {
}
void "test data"() {
given:
int datalen = service.getDataLength()
expect:
datalen > 0
}
}
Running the test ....
grails> test-app -unit -echoOut
The output ...
|Running 2 unit tests...
|Running 2 unit tests... 1 of 2
--Output from test data--
Initializing the service ...
Getting data length ...
Failure: |
test data(acme.DataServiceSpec)
|
java.lang.NullPointerException: Cannot invoke method length() on null object
at acme.DataService.getDataLength(DataService.groovy:26)
at acme.DataServiceSpec.test data(DataServiceSpec.groovy:20)
|Completed 1 unit test, 1 failed in 0m 2s
.Tests FAILED
The log shows the property initialization step and the NullPointerException for the property.
The questions are:
Why the 'data' property becomes null ?
There's a service lifecycle setting the property to null ?
Is the running test using a different DataService instance from the initialized instance ?
Have you seen Grails unit test fails on #PostConstruct?
In unit test and with #TestFor annotation #PostConstruct is not called. You can create construct for test or call setup method.
import grails.test.mixin.integration.Integration
import spock.lang.Specification
#Integration
class MySpec extends Specification {
def setup() {
}
def cleanup() {
}
void "test something"() {
expect:"tests a"
true
}
}
MySpec > test something FAILED
java.lang.IllegalStateException
Caused by: org.springframework.beans.factory.BeanCreationException
Caused by: org.springframework.beans.factory.BeanCreationException
Caused by: org.springframework.beans.factory.BeanCreationException
Caused by: java.lang.NullPointerException
1 test completed, 1 failed
:integrationTest FAILED
:mergeTestReports
I run
"test-app -integration MySpec" command
Is that an error in grails or I do smth wrong?
UPDATE!
I found a solution - just add
testCompile "org.grails.plugins:hibernate"
to build.gradle
Testing was never so easy and intuitive before the use of Spock.We can always test the exceptions in grails Spock Testing. For example we have a method which throws exception like :
String getUserType(int age){
if(age<=0){
throw new MyException("Invalid age")
}else if( age>0 && age<50){
return "Young"
}else{
return "Old"
}
}
Now we will write the test case of this method for checking whether exception is thrown for invalid inputs or not.
def "exception should be thrown only for age less than or equal to 0"{
given:
String type = getUserType(34)
expect:
type == "Young"
notThrown MyException
when:
type = getUserType(0)
then:
thrown MyException
}
This is how we have tested whether exception is thrown for invalid input or not.
Hope it helps
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