How to assert the content of a service message exception in a Grails unit test - unit-testing

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'
}
}

Related

How to check a cookie name is “not” present on page using Katalon Studio?

I need to check that a cookie is "NOT" present on-page.
Based on this post, I have tried the following on the scripted Katalon mode:
added these to the standard import from the test case:
import com.kms.katalon.core.webui.driver.DriverFactory as DriverFactory
import org.openqa.selenium.WebDriver as WebDriver
then I wrote:
WebUI.verifyMatch(driver.manage().getCookieNamed('foo'), is(null()))
and then I get the following error on null pointer
FAILED Reason:
java.lang.NullPointerException: Cannot invoke method call() on null object
Is there a way to write a check on "none" existing cookies using the script mode for Katalon Studio?
P.S:
I have tried this other approach
try {
_fbp = driver.manage().getCookieNamed('_fbp').getName()
}
catch (Exception e) {
String _fbp = new String('Something went wrong')
System.out.println('Something went wrong')
}
WebUI.verifyMatch('Something went wrong', _fbp, false)
It fails only on the verifyMatch part. It seems that 'something went wrong' does not really get stored in the variable _fbp.
FAILED.
Reason:
groovy.lang.MissingPropertyException: No such property: _fbp for class:
WebUI.verifyMatch() is used for checking matching between two strings.
You can do that using the plain Groovy assert. Instead of
WebUI.verifyMatch(driver.manage().getCookieNamed('foo'), is(null()))
do this:
assert driver.manage().getCookieNamed('foo').is(null)

Unit testing grails controllers that use declarative exception handling

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.

Grails build-test-data Plugin - Can't Find TestDataConfig.groovy

I'm trying to utilize the build-test-data plugin in my Grails (v2.4.3) app to assist with test data creation for unit testing, but while running my unit tests the plugin cannot find TestDataConfig.groovy to load my specified values (for unique constraint tests, etc).
I've installed the plugin via including it in BuildConfig.groovy:
plugins {
...
test ":build-test-data:2.2.0"
...
}
I've ran the following command to create the TestDataConfig.groovy template, which places the file at \grails-app\conf\:
grails install-build-test-data-config-template
I've followed the general instructions on the plugin wiki to come up with a properly formatted file:
testDataConfig {
sampleData {
'<path>.User' {
def a = 1
username = { -> "username${a++}" }
}
}
}
(Where path is the fully-qualified class name.)
In my tests, I am using the following general format:
import grails.buildtestdata.TestDataConfigurationHolder
import grails.buildtestdata.mixin.Build
import grails.test.mixin.TestFor
import spock.lang.Specification
import spock.lang.Unroll
#TestFor(User)
#Build(User)
class UserSpec extends Specification {
def setup() {
mockForConstraintsTests(User)
TestDataConfigurationHolder.reset()
user = User.buildWithoutSave()
}
#Unroll
void "test #field must be unique"() {
given: 'a User exists'
user.save(flush: true)
when: 'another User is created with a non-unique field value'
def nonUniqueUser = User.buildWithoutSave()
nonUniqueUser."$field" = user."$field"
then: 'validation fails and the field has a unique constraint error'
!nonUniqueUser.validate()
nonUniqueUser.errors.errorCount == 1
nonUniqueUser.errors.getFieldError("$field").code == 'unique'
where:
field << ['username', '<some other field>']
}
}
But, when the test is run (using IntelliJ IDEA) TestDataConfig.groovy cannot be found via the following method in the plugin:
static Class getDefaultTestDataConfigClass() {
GroovyClassLoader classLoader = new GroovyClassLoader(TestDataConfigurationHolder.classLoader)
String testDataConfig = Holders.config?.grails?.buildtestdata?.testDataConfig ?: 'TestDataConfig'
try {
return classLoader.loadClass(testDataConfig)
} catch (ClassNotFoundException ignored) {
log.warn "${testDataConfig}.groovy not found, build-test-data plugin proceeding without config file"
return null
}
}
So the test continues on without a config file and I do not get uniquely generated data sets.
I've even tried explicitly including the file in Config.groovy:
grails.buildtestdata.testDataConfig = "TestDataConfig"
But, the same method in the plugin shows that Holders.config? is null.
I've looked at a few solutions to a similar problem here on StackOverflow with nothing working in my case; I cannot figure out how to get my app to detect the presence of the TestDataConfig.groovy file.
Any ideas? Thanks so much!

Grails/Spock Unit Testing

I have a controller class with this code:
List<MultipartFile> files = []
List<String> convertedContents = []
def convertedFiles = [:]
try {
params.myFile.each {
if (((MultipartFile) it.value).empty) {
throw new NoUploadedFileException('Break .each closure due to empty input.')
}
files.add((MultipartFile) it.value)
}
} catch (NoUploadedFileException e) {
redirect uri: request.getHeader('referer')
return
}
convertedContents = converterService.convertToBase64(files)
(code omitted)
I also have a test:
def "sampleTest"() {
when:
controller.sendFax()
then:
thrown(NoUploadedFileException)
response.redirectedUrl == 'index.gsp'
}
What I'm trying to test is that my Controller would throw a "NoUploadedFileException" when no file are uploaded and the submit button is clicked.
This is the error:
Running 1 unit test... 1 of 1
| Failure: sampleTest(com.synacy.HomeControllerSpec)
| Expected exception com.synacy.NoUploadedFileException, but got
java.lang.NullPointerException
at org.spockframework.lang.SpecInternals.thrownImpl(SpecInternals.java:79)
at com.synacy.HomeControllerSpec.throws NoUploadedFileException and returns to the
same page when no file is uploaded(HomeControllerSpec.groovy:36)
Caused by: java.lang.NullPointerException: Cannot invoke method convertToBase64() on
null object
at com.synacy.HomeController.sendFax(HomeController.groovy:43)
at com.synacy.HomeControllerSpec.sampleTest(HomeControllerSpec.groovy:33)
It seems that it isn't going through the try-catch block, or if it is, the implementation is not working.
For a Unit test, in either setup: or when: you have to create the environment your controller is acting in.
Populate the request with whatever headers/params/data are appropriate -- headers, parameters, payload, whatever. Setup the grails application configuration with whatever is appropriate if needed.
Your NPE says that you aren't hitting the controller code you are trying to test. The NPE is because your controller doesn't have a converterService assigned/injected (it's a Unit test). You haven't set any params for your controller, so you aren't entering your .each block of code.
Perhaps controller.params.myFile = new MultipartFile() // just guessing here
Abbreviated example from one of my tests (I want to test the json response, so I have to format the request appropriately):
#TestFor(DirectoryController)
#Mock([SpringSecurityService,ConfigurationService,ConfigurationDomain,EntryDomain])
class DirectoryControllerSpec extends Specification
def "test getDirectorySources"() {
setup:
// not testing authentication, so just return true
SpringSecurityUtils.metaClass.static.ifAllGranted = { String role ->
return true
}
// mock the data to be returned from the configurationService call
def configuration = new ConfigurationDomain(id:2,name:'Mock Config',entries:[])
def typeEntry = new EntryDomain(key:'ldap01.type',value:'ad')
configuration.entries << typeEntry
def nameEntry = new EntryDomain(key:'ldap01.name',value:'LDAP01')
configuration.entries << nameEntry
// mock the configurationService
def mockConfigurationService = mockFor(ConfigurationService, true) // loose mock
mockConfigurationService.demand.getConfigurationById() { Long id ->
return configuration
}
controller.configurationService = mockConfigurationService.createMock()
when:
// setup the request attributes
request.setContentType('application/json')
request.method = 'GET'
request.addHeader('Accept','application/json')
controller.params.id = "2"
controller.getDirectorySources()
then:
response.getText() == '{"sources":[{"key":"ldap01","name":"LDAP01","type":"ad"}]}'
cleanup:
// reset the metaClass
SpringSecurityUtils.metaClass = null
}
}
Mock any services used by the controller; you aren't testing your converterService, so that should be mocked, and return a known value so you know what the controller should do in response to the data returned from the service.
In short, in a Unit test, you should control everything not in the immediate controller code.
You should mock your service so your test should look like:
#TestFor(MultipleFileUploadController)
#Mock([ConverterService])
class MultipleFileUploadControllerSpec extends Specification {
...
}
But your test will not pass because you handle NoUploadedFileException in controller, so it will not be caught anywhere in tests, so you should have fail with
Expected exception com.stackoverflow.NoUploadedFileException, but no exception was thrown
Remove the line thrown(NoUploadedFileException) from test.
Try mocking your service above your test class as:
#TestFor(MultipleFileUploadController)
#Mock([ConverterService])
This will solve your issue as spock will mock the ConverterService class for you and you can call its methods. Please keep in mind that each and every domains and services you use in your methods should be mocked in your test. Hope it will help.

Error testing thrown exceptions in Spock unit tests

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.