When I try to test for a thrown exception using the following code:
#TestFor(EncryptionService)
class EncryptionServiceSpec extends Specification {
def "test decryption of unecnrypted file"(){
setup:
def clearTextFile = new File("test/resources/clearText.txt")
clearTextFile.write("THIS IS CLEAR TEXT")
when:
def (privateKey,publicCert) = service.generateKeyPair("123")
service.decryptFile(new FileInputStream(clearTextFile), privateKey )
then:
clearTextFile.delete()
thrown GeneralSecurityException
}
}
I get the following compilation exception when I run either grails test-app -unit
Unexpected error during compilation of spec 'com.genospace.services.EncryptionServiceSpec'. Maybe you have used invalid Spock syntax? Anyway, please file a bug report at http://issues.spockframework.org.
java.lang.ClassCastException: org.codehaus.groovy.ast.expr.ArgumentListExpression cannot be cast to org.codehaus.groovy.ast.expr.VariableExpression
at org.codehaus.groovy.ast.expr.DeclarationExpression.getVariableExpression(DeclarationExpression.java:103)
at org.spockframework.compiler.SpecRewriter.moveVariableDeclarations(SpecRewriter.java:538)
Try without leveraging Groovy's multi-assignment feature (def (privateKey,publicCert) = ...). If this solves the problem (and I think it will), please file an issue at http://issues.spockframework.org.
Related
I am using Grails 4.0.3 and want to assert that an exception is thrown in a given situation. Below, my PidService.
def validatePidIssuingConclusionDocument(JSONObject pidIssuingConclusionDocument){
String message = "Document issuing number is mandatory"
if(!pidIssuingConclusionDocument.has("docIssuingNumber")){throw new Exception(message)}
}
Below, my test case:
void "wrong document"() throws Exception {
JSONObject documentWithoutIssuingNumber = new JSONObject()
documentWithoutIssuingNumber.accumulate("docIssuingNumber","123")
pidService.buildPidIssuingOrder(documentWithoutIssuingNumber)
// How can I assert that the exception is thrown and verify it message.
}
I tried to use try/catch in the test case without success. Could anyone help me? I need to assert that the exception is thrown and the message is Document issuing number is mandatory in the given case.
I need to assert that the exception is thrown and the message is
Document issuing number is mandatory in the given case.
I can't provide an executable example around the code you provided because some things are missing (like buildPidIssuingOrder). See the project at https://github.com/jeffbrown/dnunesexception which contains an example that shows a way to deal with the exception in a test though.
grails-app/services/dnunesexception/PidService.groovy
package dnunesexception
import org.grails.web.json.JSONObject
class PidService {
def buildPidIssuingOrder(JSONObject pidIssuingConclusionDocument) {
throw new Exception('Document issuing number is mandatory')
}
}
src/test/groovy/dnunesexception/PidServiceSpec.groovy
package dnunesexception
import grails.testing.services.ServiceUnitTest
import spock.lang.Specification
import org.grails.web.json.JSONObject
class PidServiceSpec extends Specification implements ServiceUnitTest<PidService>{
void "test something"() {
when:
JSONObject documentWithoutIssuingNumber = new JSONObject()
documentWithoutIssuingNumber.accumulate("docIssuingNumber","123")
service.buildPidIssuingOrder(documentWithoutIssuingNumber)
then:
def e = thrown(Exception)
and:
e.message == 'Document issuing number is mandatory'
}
}
I am running my Junit test cases for my groovy class using spock framework I am using Mock to invoke my class. but it is giving me MissingMethodException but if I invoke the same method by normal creating object def obj = new MyClass() way it is working. please let me know am I missing something? below is my stacktrace
Expected no exception to be thrown, but got 'groovy.lang.MissingMethodException'
at spock.lang.Specification.noExceptionThrown(Specification.java:119)
at .AsplTest.fetchXmlTest(AsplTest.groovy:35)
Caused by: groovy.lang.MissingMethodException: No signature of method: com.webservice.Service.fetchAsplXml() is applicable for argument types: (java.lang.String, groovy.net.xmlrpc.XMLRPCServerProxy, java.lang.String) values: [3c98fa0dd1b5d92af599779bfb7be655, groovy.net.xmlrpc.XMLRPCServerProxy#797b0699, ...]
Possible solutions: getFetchAsplXml()
at .AsplTest.fetchXmlTest(AsplTest.groovy:33)
below is my test code
public void fetchXmlTest() {
given:
def asplObject=Mock(Service);
when:
asplObject.fetchXml(sessionId, serverProxy, "https://serverproxy")
then:
noExceptionThrown()
}
FYI:
my groovy version is 2.4.12 and spock version 1.1-groovy-2.4
It seems to me that you are doing things backwards.
Mocks are not test subjects. They are used to control the interactions of your test subjects with other objects. It looks, from the code you posted, that you want to test the invocation of method fetchXml on your Service object.
To do this, you need to create an instance of Service, and call the method. If your Service has collaborating objects, then you can Mock them, and add interactions, like this:
given:
def service = new Service()
and:
service.collaboratingObject = Mock(CollaboratingObjectClass)
when:
service.getFetchAsplXml()
then:
1 * service.collaboratingObject.someMethodReturningAString(_ as String) >> {String input-> "mockedResult from $input" as String }
Let's say I have the following code:
class SomeController {
def fooService
def controllerMethod() {
def bar = fooService.doSomething()
// render bar to user - success case
}
def fooExceptionHandler(FooException e) {
// log, render error page, etc...
}
}
Based on grails' new declarative controller exception handling mechanism, if fooService.doSomething() throws an exception, grails will call fooExceptionHandler for me. Great.
Now when I unit test this method (test class uses the #TestFor(SomeController) annotation), this will fail saying that we expected a FooException but got nothing.
#Test(expected=FooException)
def doSomethingThrowsFooException() {
// override default service behavior, trigger a FooException
controller.fooService = [ doSomething: { throw new FooException() }]
controller.controllerMethod()
}
However, this works:
#Test
def doSomethingThrowsFooException() {
// override default service behavior, trigger a FooException
controller.fooService = [ doSomething: { throw new FooException() }]
controller.controllerMethod()
assert response.json == false
}
So the only way to test this method is by asserting that the response was what was expected but due to the declarative exception handling, this logic is now somewhere else (tested in isolation), not in the unit of code I am testing. Shouldn't my unit test only verify that the exception was propagated out of the controller method?
I would test the fooService integration with your controller in an integration test if possible, but I think that's only really testable sensibly in a functional test. You're really testing Grails - you're verifying that documented behavior occurs in your app.
If you add some code to throw an exception and then extra code to catch it and route it to the handler, you're just mocking out the stuff that Grails provides. Tests of that just test your mocking code, but have little to do with how well your code will work in production.
The unit test opportunity here is inside fooExceptionHandler. Test that given an exception, you do the right thing with it.
I have existing UnitTests written extending grails' GrailsUnitTestCase. I wrote new Unit Tests using Spock framework. Running individual Spock Spec with following command is fine.
prayag#prayag:~/gccount$ grails test-app spock: ChronicSpec
But running existing UnitTests throws compilation error in Spock Tests.
prayag#prayag:~/gccount$ grails test-app unit: ChronicUnitTest.testDefaultChronic
| Error Compilation error compiling [unit] tests: startup failed:
/home/prayag/gccount/test/unit/com/zazzercode/chronic/ChronicSpec.groovy: 45: unexpected token: } # line 45, column 5.
} //end of response process
^
1 error
ChronicSpec.groovy is as below
class ChronicSpec extends Specification {
final public String CHRONIC_DEFAULT_METRIC = ReportType.CHRONIC_REPORT + Constants.COLON + ChronicMetrics.DEFAULT
final public String INDEX_NAME = "gccount"
ChronicService chronicService
void "when response is processed json should be created"() {
given:
def contentBuilder = XContentFactory.jsonBuilder().startObject()
chronicService = new ChronicService()
//other code goes here
when:
listener.writeJson(records, contentBuilder, "chronic")
then:
//assertion goes here
} //end of response process => this is where exception is thrown
}
Tools 'm using
grails : 2.2.3
spock : 0.7
I am surprised this actually compiles, you cannot leave an empty "then:" block.
You need at least one assertion. As suggested by Sergio Michels, add an assertion and it should fix it.
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