I have a small Groovy Class called "zzz". The purpose of this class is to first demonstrate successfully passing a binding to the template engine producing an output and then failing to bind to another template engine using what appears to be the same set of bindings.
V1.template contains the base message that will be used with the bindings to produce a final output. V1.properties contains an XPath expression that should grab the value from an XML document and add it to the bindings. T1.xml is the raw xml input file.
In the zzz Groovy Class I have hard coded the LastName in bindings1 and that works. But, when I grab the lastName value from the XML file and add it to bindings2 it fails. Both bindings appear to have exactly the same text, but I have noticed that bindings1 is of type Bindings and binding2 is of type Reference.
I assume that bindings2 being of Reference is what is causing my problem, but I don't know how to cast or convert it to Binding. Please let me know what I'm doing wrong.
I'm using Java 1.8 with groovy-all-2.3.10.jar
zzz.groovy:
import java.io.File;
import javax.xml.xpath.*
import javax.xml.parsers.DocumentBuilderFactory
class zzz {
def xpath
def records
def loadDocToCheck(File docToCheck) {
xpath = XPathFactory.newInstance().newXPath()
def builder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
def inputStream = new FileInputStream( docToCheck )
records = builder.parse(inputStream).documentElement
}
def validateXpath(String xpathQuery ) {
def nodes = xpath.evaluate( xpathQuery, records, XPathConstants.NODESET )
nodes.collect { node -> node.textContent }
def nodeCount = 0
nodes.each { nodeCount++ }
nodeCount
}
def getXpath(String xpathQuery ) {
String retVal = ""
def nodes = xpath.evaluate( xpathQuery, records, XPathConstants.NODESET )
nodes.collect { node ->
retVal += node.getTextContent()
}
(retVal)
}
static main(args) {
def zzz = new zzz()
def testFile = new File("T1.xml")
zzz.loadDocToCheck(testFile)
def config = new ConfigSlurper().parse(new File("V1.properties").toURI().toURL())
String testFileNameOnly = testFile.getName()-testFile.getParent()
def bindings1 = [
"InputFile" : "$testFileNameOnly",
"LastName" : "Smith"
]
def templateFile1 = new File('V1.template')
println "templateFile1=${templateFile1.getAbsolutePath()}"
def engine1 = new groovy.text.GStringTemplateEngine()
def template1 = engine1.createTemplate(templateFile1).make(bindings1)
println template1.toString()
println "******************************"
def bindings2 = [:]
bindings2 << ["InputFile":"$testFileNameOnly"]
config.params.each { paramName, param ->
bindings2 << ["$paramName" : "${zzz.getXpath(param)}"]
}
println "bindings2=$bindings2"
def templateFile2 = new File('V1.template')
println "templateFile=${templateFile2.getAbsolutePath()}"
def engine2 = new groovy.text.GStringTemplateEngine()
def template2 = engine2.createTemplate(templateFile2).make(bindings2)
println template2.toString()
}
}
T1.xml:
<?xml version="1.0"?>
<MyRoot specVersion="3.03">
<employee>
<lastName>Smith</lastName>
<firstName>John</firstName>
</employee>
</MyRoot>
V1.template:
Input file: ${InputFile}
LastName: ${LastName}
V1.properties:
params {
LastName = '//MyRoot/employee/lastName/text()'
}
I found why the second template would could execute. The bindings must be in the form of Map, but I was passing in a GString as the key for the map. Note: "$parameterName" is a GString. After converting the key to a String the second template executed correctly.
Related
I am new to groovy and Spock.
I'm trying to create a generic method for mocking objects in my system.
the problem
I'm trying to create a function that will get an object and dynamically mock the functions I want in the object.
the function gets a map of functions with data when to mock each of one them and what to return.
the functions return an error.
I created a class
class MetaData {
Object[] argTypes
def returnValue
Object[] argsMatchers
MetaData(Object[] argTypes, returnValue, Object[] argsMatchers) {
this.argTypes = argTypes
this.returnValue = returnValue
this.argsMatchers = argsMatchers
}
}
the mocking function is:
def mockFunctionTestData(Map overrides = [:], def clazz){
def args = Mock(clazz)
overrides.each { String key, value ->
Object[] argTypes = value.argTypes
if(args.metaClass.respondsTo(args, key, argTypes).size() == 1){
def methodToGetRequest = key
def argsMatchers = value.argsMatchers
def returnValue = value.returnValue
args."$methodToGetRequest"(*argsMatchers) >> returnValue
} else {
println "Error: Trying to add property that doesn't exist"
}
}
return args
}
I'm creating the object :
def functionData = new MetaData([Date, Date, List, boolean] as Object[],
meas,
[_ as Date, _ as Date, new ArrayList<>(), true] as Object[]) //the line that fails
def dogDAO = [getDogData: functionData]
def testDog= mockFunctionTestData(dogDAO , Dog)
the code above returns the following exception:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '_' with class 'org.spockframework.lang.Wildcard' to class 'java.util.Date' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.util.Date(org.spockframework.lang.SpreadWildcard)
the line that fails
[_ as Date, _ as Date, new ArrayList<>(), true] as Object[])
In Spock Framework, you can't create a mock in such a dynamic fashion. Spock has its own compiler (AST Transformation to be precise) which creates an executable test code. Only when in interaction section, does it recognize "_" as a wildcard symbol and ">>" operator to return a fixed value. That's why you get that exception. Because "_" wildcard is not in an interaction section. I'd suggest writing your test similar to the following:
class DogSpec extends Specification {
def "test the dog"() {
when:
def dog = Mock(Dog) {
1 * getDogData(_ as Date, _ as Date, new ArrayList<>(), true) >> "Bark"
}
then:
dog.getDogData(new Date(), new Date(), [], true) == "Bark"
}
}
Where to declare interactions
Declaring Interactions at Mock Creation Time
Returning Fixed Values
Example TagLib:
I need to mock the 'params' to be used in some request
class MyTagLib {
static namespace = 'p'
format = { attrs -->
def siteId = params.siteId // I need to mock this
def domainLanguage = params.domainLanguage.toString()
.
.
.
}
You should start by looking at http://grails.github.io/grails-doc/latest/guide/testing.html#unitTestingTagLibraries
And in your case you can probably do something like:
#TestFor(MyTagLib)
class MyTagLibSpec extends Specification {
def "test something with params"() {
given:
params.siteId == "mySiteId"
params.domainLanguage = new DomainLanguage()
when:
def result = tagLib.format(attr1: 'someAtribute').toString()
then:
result == 'expectedOutput'
}
}
But I would definetly try and read the documentation first :-)
I'm trying to do a Unit test on this controller. I'm new to this sort of testing so I dont know from where do I start and how to test things that are needed to be tested, like user, render view.)
class ShoppingCartController {
def shoppingCartWebshopService
def shoppingCartService
def springSecurityService
def checkoutOperaService
def databaseService
def dodAdresaService
def payingOrder(SetShop1Command cmd) {
def user = springSecurityService.isLoggedIn() ? springSecurityService.currentUser.sifpartnera : null
def tempAdrese = databaseService.getAdrese(user)
def adrese = []
tempAdrese.each{
adrese.add(it.adresa)
}
if (cmd.hasErrors()) {
render(view: 'OrderChoseAddress', model: [cmd : cmd, params : params, adrese: adrese ])
}
def inputUnAdrese = params.inputUnAdrese
[inputUnAdrese: inputUnAdrese, adrese: adrese]
}
This is my test
#Mock([SpringSecurityService,DatabaseService])
#TestFor(ShoppingCartController)
class ShoppingCartControllerTests {
void testPayingOrder(){
when:
// params.user = 19
// user.equals(id)
// println user
// controller.OrderChoseAddress()
controller.params.user = "admin"
controller.databaseService = new DatabaseService()
then:
assert model.adrese != null
}
i have tagLib like this:
static namespace = 'j2'
def brandMessage = { attrs, body ->
def brand = ConfigurationHolder.config.j2.brand
def messageCode = (brand ? brand+".":"") + attrs.code
def defaultCode = attrs.default ?: attrs.code
out << message(code:messageCode, default:message(code:attrs.code,default:defaultCode))
}
and using in :
public static def translate = {code,Object[] args->
def dflt = (args.size()>0?args[0]:"");
def taglib = ApplicationHolder.application?.getMainContext()?.getBean("com.j2.taglib.BrandMessageTagLib")
def translatedValue = taglib?.brandMessage(code:code,default:dflt)?:""
return translatedValue
}
in controller we are using :
flash.message = I18nUtils.translate('admin.groups.delete.success')
while running the app its working fine. But when we are creating the Unit test case for the controller it throwing the error message like this:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'com.j2.taglib.BrandMessageTagLib' is defined
but i defined this in the Test class like this:
defineBeans {
myService(BrandMessageTagLib)
}
def beanName=applicationContext.getBean("myService")
log.info("beanName->"+beanName)
def mockMyTagLib = mockFor(BrandMessageTagLib)
mockMyTagLib.demand.brandMessage(1) {code, defaultMessage ->
def defCode = new MarkupBuilder(new StringWriter())
defCode.applyTemplate('<j2:brandMessage code="admin.groups.delete.success"')
}
controller.brandMessageTagLib = mockMyTagLib.createMock()
Even this is also same errormessage throwing.
anybody have idea is a greate helpfull.
Thanks
arnagendla
I have a service class method in my grails porject which uses a helper class to fetch the response as xml. The xml is then send out as the response of the service class method.
ServiceClass:-
class ItemService{
def getItem(Number) {
def HelperClass helper = new HelperClass()
def responseXml = helper.getMessage(Number)
return responseXml
}
}
I writing a test case for this method. In my test case, i wish to mock
def responseXml = helper.getMessage(Number)
The test case that i have written so far is:
class ItemServiceTest extends GroovyTestCase {
public final void testFindItem(){
def service = new ItemService()
def xml = "<Item><Number>123</Number></Item>"
def mockJobServiceFactory = new MockFor(HelperClass)
mockJobServiceFactory.demand.getMessage{ def str ->
return xml
}
service.getItem().HelperClass = mockJobServiceFactory.proxyInstance()
def item = service.getItem()("123")
assertNotNull(item)
}
but still, the mock does not return the xml that I speicified in the test case.
Any problems that you see in the above approach?...Advance Thanks
When you mock objects with MockFor, you need to surround the code that uses the mock in a use closure. Try this:
def service = new ItemService()
def xml = "<Item><Number>123</Number></Item>"
def mockJobServiceFactory = new MockFor(HelperClass)
mockJobServiceFactory.demand.getMessage{ def str ->
return xml
}
mockJobServiceFactory.use {
def item = service.getItem()("123")
assertNotNull(item)
}