I'm studying Grails framework and developing an application.
At the moment I have a main application which has severals plugins.
So the hierarchy is like that :
MyMainApp
MyFirstPlugin
MySecondPlugin
...
I would like to write UrlMappings tests for my plugins. I wrote the doc and I'm probably missing something but I can't pass those f** tests. I always catch the error
java.lang.IllegalArgumentException: url '/bar' did not match any mappings
Here is my FooUrlMappings class
class FooUrlMappings {
static mappings = {
"/bar/"(controller: 'foo', action: 'show')
}
}
Note that my FooUrlMappings class is in the default package in /conf directory.
Now the code of my controller FooController :
package be.arexo.ehr.employee.rest
import be.arexo.ehr.employee.Employee
import grails.converters.JSON
class FooController {
// GET /bar/
def show() {
def result = Bar.list()
render result as JSON
}
}
So now, my test class :
import com.example.FooController
import grails.test.mixin.Mock
import grails.test.mixin.TestFor
import grails.test.mixin.web.UrlMappingsUnitTestMixin
#TestFor(FooUrlMappings)
#Mock(FooController)
class FooUrlMappingsTests {
void testBarShow(){
assertForwardUrlMapping("/bar/", controller : "foo", action : "show")
}
}
My test is also in the default package in the test/integration directory.
So I think that I did what is said in the documentation. If I try to run this test I will get :
java.lang.IllegalArgumentException: url '/bar' did not match any mappings
Where is my mistake ? Can someone help me please ?
You should run URL mappings tests as unit tests, not as integration tests. This will solve your problem.
#TestFor(FooUrlMappings)
Note that the TestFor annotation can only be used in unit tests.
My test is also in the default package in the test/integration
directory.
Move your test to the test/unit/ directory.
Related
I'm attempting to create unit tests for a JenkinsShared library using Gradle in order to run the test tasks.
I've followed this tutorial which upon conclusion one has a working test suite for a shared library for functions within the vars folder (with the unit tests in src/test/groovy/*Test.groovy).
However, in our internal shared jenkins library we followed a more object oriented style and isolated functionality into a package of classes in the format: src/org/company/*.groovy.
The problem arises when attempting to import said package into a unit test class. In the tutorial, the functions are imported using the loadScript method this method fails when loading a class which is dependent on another file.
Take the class:
package tests
import org.junit.*
import com.lesfurets.jenkins.unit.*
import static groovy.test.GroovyAssert.*
import org.company.UtilFactory
class UtilFactoryTest extends BasePipelineTest {
#Test
void testCall() {
def util = UtilFactory.getUtil("hello")
assertEquals true, true
}
}
src/org/company/UtilFactory.groovy
package org.company
class UtilFactory implements Serializable {
static Util instance
static Util getUtil(script=null) {
if (!(UtilFactory.instance)) {
if (!script) {
// Throws an exception if on the first call to getUtil the
// script parameter is null.
throw new ScriptUndefinedException("script parameter null on initial call to getUtil")
}
UtilFactory.instance = new Util(script)
}
return UtilFactory.instance
}
}
class ScriptUndefinedException extends Exception {
// Parameterless Constructor
public ScriptUndefinedException() {}
// Constructor that accepts a message
public ScriptUndefinedException(String message)
{
super(message);
}
}
Which gives me the exception:
jenkins-utilities/src/test/groovy/UtilFactoryTest.groovy: 7:
unable to resolve class org.company.UtilFactory
# line 7, column 1.
import org.company.UtilFactory
This may be more of a Gradle issue than a JenkinsShared Library. I've just spent a good portion of my day trying to figure out exactly what I'm doing wrong to no avail.
I would really appreciate any help to guide me in the right direction.
This library may be helpful getting your shared libraries to work in the unit test https://github.com/stchar/pipeline-sharedlib-testharness
I am setting up a shared library for Jenkins pipelines and am trying to figure out how to import a class in the shared library into a custom step that I am writing.
Here's what the directory structure looks like:
src
--jenny
----util
------Versioning.groovy
vars
--calculateVersion.groovy
The Versioning.groovy file defines some static helper methods that do some stuff.
package jenny.util
class Versioner implements Serializable {
static bool checkForValidVersion(version) {
return true
}
}
I would like to call this method from the calculateVersion.groovy something like this:
def call(version) {
return jenny.util.Versioner.checkForValidVersion(version)
}
So that my declarative pipeline can call:
def valid = calculateVersion "1.0.0"
But I receive this error No such property: jenny for class: calculateReleaseVersions
Is it possible to reference the classes in the shared library from files in the vars to define custom steps and how is this done?
Yes it is possible. At least for us:
Just like in plain java (or groovy) we put an import statement into the groovy script in vars. In your case that would be something like:
import jenny.util.Versioner
def call(version) {
return Versioner.checkForValidVersion(version)
}
Another thing I just found: It looks like the file name of the class Versioner doesn't match the class name: Versioning.groovy. Could that be the issue?
If that doesn't work you propably want to upgrade your pipeline plugin version(s).
I'm playing around with Grails/Groovy and have some straight Groovy code working that utilizes groovy-wslite. That code starts as such
send-request.groovy
#Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='1.1.0')
import wslite.soap.*
When I implement that into my Grails code and view the controller/action I get this
Error 500: Internal Server Error
URI: /FormProj/hello/trigger
Class: java.lang.RuntimeException
Message: No suitable ClassLoader found for grab
And here's the code in it's current state (I've tried a LOT of different things)
HelloController.groovy
package com.demo
import groovy.grape.Grape
class HelloController {
def index() { }
def sayHi() {
return [
greeting : "Hi there, ${ params.name }"
]
}
def trigger() {
Grape.grab(group:'com.github.groovy-wslite', module:'groovy-wslite', version:'1.1.0')
…
}
}
As I'm sure you notice I'm very green with Grails/Groovy and really all things Java. I do know there is a wslite plugin for Grails, but surely this can work too right?
Grails: 2.3.8
Groovy: 2.2.2
UPDATE
Based on Ian Robert's advice I have updated my BuildConfig file by adding this line to the dependencies block
compile 'com.github.groovy-wslite:groovy-wslite:1.1.0'
And updated my controller to look like this
HelloController.groovy
package ws.thejspot
import wslite.soap.*
class HelloController {
def index() { }
def sayHi() {
return [
greeting : "Hi there, ${ params.name }"
]
}
def trigger() {
def client = new SOAPClient('URL')
}
}
Unfortunately now the IDE, GGTS, shows an error in the controller 'unable to resolve class SOAPClient'
Rather than trying to download the dependencies with #Grab, you should use the standard Grails dependency mechanism - edit grails-app/conf/BuildConfig.groovy and look for the grails.project.dependency.resolution closure. Inside that, in the dependencies block you should add
compile 'com.github.groovy-wslite:groovy-wslite:1.1.0'
and remove anything Grape-related from the controller, leaving just the import wslite.soap.*
You will probably need to run
grails compile --refresh-dependencies
at least once to ensure that Grails picks up your change to BuildConfig - it deliberately doesn't do a full dependency resolve every time you compile, so as not to slow down the build too much, so you need to tell it to refresh when you know it needs to.
we are preparing for Grails 2.4 upgrade. One of the issues we face is that
most of the command object unit tests fails because of injected properties, like
services, are required to be not null during validation.
Is there any suggested way how to test this? Should we mock all properties although some are not needed for test? or is there a way to do this differently?
After my question is answered by Jeff, I share links with more information about new functionalities:
doWithSpring and doWithConfig are shortly described in What's new in 2.4: http://grails.org/doc/latest/guide/introduction.html#whatsNew24 in Unit Testing improvements section
There is also a JIRA issue with example: https://jira.grails.org/browse/GRAILS-11003
Most unit tests don't want or need the application context all spun up and populated. Unit tests can add whatever they want (or nothing) to the application context. In recent versions of Grails you can do something like this...
A controller and command object:
// grails-app/controllers/demo/DemoController.groovy
package demo
class DemoController {
def processName(SomeCommand co) {
render co.someValue
}
}
class SomeCommand {
String name
def helperService
def getSomeValue() {
helperService.processValue(name)
}
}
A service:
// grails-app/services/demo/HelperService
package demo
class HelperService {
def processValue(String originalValue) {
"__${originalValue}__"
}
}
A unit test:
// grails-app/test/unit/demo/DemoControllerSpec.groovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(DemoController)
class DemoControllerSpec extends Specification {
def doWithSpring = {
helperService HelperService
}
void 'process name'() {
when:
params.name = 'Jeff'
controller.processName()
then:
response.contentAsString == '__Jeff__'
}
}
That test will pass with Grails 2.4.2.
I hope that helps.
I have built a new basic grails project. I have a basic java object I've written outside of grails, and jarred up. I've added the jar file to the grails project, via the properties > Java build path > Libraries tab > Add Jars.
Then I try to access it in a grails controller, and get a class def not found error.
What am I doing wrong?
TestController.groovy
package testproject
import test.TestClass
class TestController {
def index() {
def testClass = new TestClass()
render 'Index page'
}
}
and:
in the jar, TestClass.java
package test;
public class TestClass {
private String string;
public void setString(String string)
{
this.string = string;
}
public String getString()
{
return string;
}
}
The error is:
C:\Users\One\TestProject\grails-app\controllers\testproject\TestController.groov
y: 3: unable to resolve class test.TestClass # line 3, column 1.
import test.TestClass
The STS classpath generated from the Grails classpath, but it's unidirectional. Adding items in STS has no effect on Grails.
Put the jar file in your lib directory and run grails compile --refresh-dependencies. Then re-sync STS from Grails by right-clicking the project node in the tree and running Grails Tools | Refresh Dependencies.
You still need to import it in the Grails controller.
import your.java.ClassName