I'm trying to test a method which throws different exceptions according to the messages in the exceptions it receives.
I'm having a hard time throwing a SOAPFaultException because its constructor expects a SOAPFault which is an interface.
So I need to mock an interface or a different approach. This project uses grails 2.2.4 and junit 4.10.
Any help is appreciated.
The code:
import javax.xml.ws.BindingProvider
import javax.xml.ws.soap.SOAPFaultException
class CatalogClientService {
AplicacaoPT aplicacaoPT = new AplicacaoSoapService().getAplicacaoSoapPort()
static transactional = false
def fetch(String codigoBuscado) {
try {
def response = aplicacaoPT.buscaAplicacaoPorCodigo(codigoBuscado)
def app = response[0].serviceData.aplicacao[0]
def appGeral = app.getGeral()
def allTags = app.palavras.palavraChave.findAll().collect { it }
def tags = allTags.unique()
[name: appGeral.nome, description: appGeral.descricao, tags: tags, admins: [appGeral.getLiderProjeto().getChave()]]
} catch (SOAPFaultException e) {
if (e.fault.faultString == "Provider Error") {
throw new IllegalArgumentException("Nenhuma aplicação encontrada com o código ${codigoBuscado}.", e)
}
throw new RuntimeException("Erro ao buscar aplicação de código ${codigoBuscado}.", e)
} catch (Exception e) {
throw new RuntimeException("Erro ao buscar aplicação de código ${codigoBuscado}.", e)
}
}
}
import grails.test.mixin.*
import grails.test.mixin.support.GrailsUnitTestMixin
import org.junit.*
import javax.xml.ws.soap.SOAPFaultException
import javax.xml.soap.SOAPFault
#TestFor(CatalogClientService)
class CatalogClientServiceTests {
final shouldFailWithCause = new GroovyTestCase().&shouldFailWithCause
void testFetchFailsWithInvalidApplicationCode() {
def fault = new Expando()
fault.metaClass.getFaultString = { -> "Provider Error" }
SOAPFaultException.metaClass.'static'.getFault = { -> fault }
AplicacaoPT.metaClass.buscaAplicacaoPorCodigo = { String id -> throw new SOAPFaultException() }
shouldFailWithCause(SOAPFaultException) { service.fetch("POPB") }
}
}
If all you want is a simple way to create an instance of SOAPFault you should be able to do something like this...
import javax.xml.ws.soap.SOAPFaultException
import javax.xml.soap.SOAPFault
// ...
new SOAPFaultException({} as SOAPFault)
If you want to provide some method implementations, like getFaultString() for example, you can do someting like this...
import javax.xml.ws.soap.SOAPFaultException
import javax.xml.soap.SOAPFault
// ...
def soapFault = [getFaultString: { 'some message'}] as SOAPFault
new SOAPFaultException(soapFault)
I hope that helps
Related
I'm trying to mock newInstance() and call() in groovy.sql.Sql:
package com.sample
import grails.test.GrailsUnitTestCase
import groovy.mock.interceptor.MockFor
import groovy.sql.Sql
class MySampleTests extends GrailsUnitTestCase {
void testThat_SqlCall_IsInvokedWithexpectedQuery() {
def mockSql = new MockFor(Sql.class)
mockSql.demand.newInstance { def datasource->
return mockSql
}
mockSql.demand.call { def sql ->
return 0
}
mockSql.use {
MySample targetObject = new MySample()
targetObject.myMethod()
}
}
}
Where this is the target code:
package com.sample
import groovy.sql.Sql
class MySample {
def dataSource
def myMethod() {
def conn = Sql.newInstance(dataSource)
conn.call("test")
}
}
It errs out with:
groovy.lang.MissingMethodException: No signature of method: groovy.mock.interceptor.MockFor.call() is applicable for argument types: (java.lang.String) values: [test]
The error makes it seem like the call() method is not being mocked. Is that the case? What's a fix for it?
Replacing mockSql.demand.call with mockSql.metaClass.call provides a mocked method, but requires manual verification that the method is called, and of the parameter values:
package com.sample
import grails.test.GrailsUnitTestCase
import groovy.mock.interceptor.MockFor
import groovy.sql.Sql
class MySampleTests extends GrailsUnitTestCase {
void testThat_SqlCall_IsInvokedWithexpectedQuery() {
def mockSql = new MockFor(Sql.class)
def callInvoked = 0
mockSql.demand.newInstance { def datasource->
return mockSql
}
mockSql.metaClass.call { def sql ->
assert sql == "test"
++callInvoked
return 0
}
mockSql.use {
MySample targetObject = new MySample()
targetObject.myMethod()
}
assert callInvoked == 1
}
}
I don't know enough groovy yet to understand why this is the case, but it solved the issue for me.
Additional cosmetic changes plus moving the targetObject instantiation out of mySql.use {} result in:
package com.sample
import grails.test.GrailsUnitTestCase
import groovy.mock.interceptor.MockFor
import groovy.sql.Sql
class MySampleTests extends GrailsUnitTestCase {
MySample targetObject = new MySample()
void testThat_SqlCall_IsInvokedWithexpectedQuery() {
def mockSql = new MockFor(Sql)
def callInvoked = 0
mockSql.demand.newInstance { datasource->
mockSql
}
mockSql.metaClass.call { sql ->
assert sql == "test"
++callInvoked
0
}
mockSql.use {
targetObject.myMethod()
}
assert callInvoked == 1
}
}
Im doing restfull webservices with soap using websphere and RAD. After generating my javaclient classes when I run the test class I get the following error. Ive been searching the web but not finding the correct solution. PLEASE HELP!
ERROR:
Check method call
org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at org.apache.xerces.dom.CoreDocumentImpl.insertBefore(Unknown Source)
at org.apache.xerces.dom.NodeImpl.appendChild(Unknown Source)
at com.ibm.ws.webservices.engine.xmlsoap.SOAPPart.appendChild(SOAPPart.java:282)
at com.sun.xml.internal.bind.marshaller.SAX2DOMEx.startElement(SAX2DOMEx.java:177)
at com.sun.xml.internal.ws.message.AbstractMessageImpl.writeTo(AbstractMessageImpl.java:159)
at com.sun.xml.internal.ws.message.AbstractMessageImpl.readAsSOAPMessage(AbstractMessageImpl.java:194)
at com.sun.xml.internal.ws.handler.SOAPMessageContextImpl.getMessage(SOAPMessageContextImpl.java:80)
at test.CustomSoapHandler.handleMessage(CustomSoapHandler.java:37)
at test.CustomSoapHandler.handleMessage(CustomSoapHandler.java:1)
at com.sun.xml.internal.ws.handler.HandlerProcessor.callHandleMessage(HandlerProcessor.java:293)
at com.sun.xml.internal.ws.handler.HandlerProcessor.callHandlersRequest(HandlerProcessor.java:134)
at com.sun.xml.internal.ws.handler.ClientSOAPHandlerTube.callHandlersOnRequest(ClientSOAPHandlerTube.java:139)
at com.sun.xml.internal.ws.handler.HandlerTube.processRequest(HandlerTube.java:117)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:599)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:558)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:543)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:440)
at com.sun.xml.internal.ws.client.Stub.process(Stub.java:223)
at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:136)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:110)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:90)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:119)
at $Proxy33.getHistory(Unknown Source)
at test.ServiceTest.historyTest(ServiceTest.java:64)
at test.ServiceTest.main(ServiceTest.java:100)
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.J9VMInternals.initialize(J9VMInternals.java:227)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:90)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:119)
at $Proxy33.getHistory(Unknown Source)
at test.ServiceTest.historyTest(ServiceTest.java:64)
at test.ServiceTest.main(ServiceTest.java:100)
Caused by: java.lang.ClassCastException: com.ibm.xml.xlxp2.jaxb.JAXBContextImpl incompatible with com.sun.xml.internal.bind.api.JAXBRIContext
at java.lang.ClassCastException.<init>(ClassCastException.java:58)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.<clinit>(SOAPFaultBuilder.java:545)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:205)
... 6 more
Test Class:
package test;
import be.ipc.css.ws.GcssWebServiceService;
import be.ipc.css.ws.IGcssWebService;
import be.ipc.css.ws.InvalidItemIdStructureFault_Exception;
import be.ipc.css.ws.ProductNotAllowedFault_Exception;
import be.ipc.css.ws.common.Product;
import be.ipc.css.ws.history.GetHistoryInput;
import be.ipc.css.ws.history_output.GetHistoryOutput;
import be.ipc.css.ws.history_output.HistoryItem;
import be.ipc.css.ws.history_output.Type;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.handler.Handler;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* <strong>Project: TODO: project name</strong><br/>
* <b>Url:</b> TODO: url<br/>
* <b>Date:</b> 15.05.14<br/>
* <b>Time:</b> 23:42 <br/>
* Copyright(C) 2014 IT Service Plus <br/>
* <b>Description:</b><br/>
* TODO: description
*/
public class ServiceTest {
private static Service webService;
private static IGcssWebService servicePort;
public void initService() throws MalformedURLException {
URL url = new URL("http://cs-demo.ipc.be/CSS_UA2/services/gcssWebService/1.0");
QName qname = new QName("http://ws.css.ipc.be/", "GcssWebServiceService");
/*java.util.Properties props = System.getProperties();
props.setProperty("http.proxyHost", "proxy.test.com");
props.setProperty("http.proxyPort", "8080");*/
webService = GcssWebServiceService.create(url, qname);
servicePort = webService.getPort(IGcssWebService.class);
try {
CustomSoapHandler sh = new CustomSoapHandler("user_us", "*******");
List<Handler> new_handlerChain = new ArrayList<Handler>();
new_handlerChain.add(sh);
((BindingProvider)servicePort).getBinding().setHandlerChain(new_handlerChain);
} catch (Throwable e) {
e.printStackTrace();
}
//((BindingProvider)servicePort).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "user_us");
//((BindingProvider)servicePort).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "*******");
}
public void historyTest() throws ProductNotAllowedFault_Exception, InvalidItemIdStructureFault_Exception {
GetHistoryInput input = new GetHistoryInput();
input.setItemId("CC027607063NL");
input.setProduct(Product.EPG);
System.out.println("Check method call");
GetHistoryOutput output = servicePort.getHistory(input);
System.out.println("Check result");
//Assert.assertNotNull(output);
//Assert.assertNotNull(output.getHistory());
//Assert.assertNotNull(output.getHistory().getHistoryItem());
System.out.println("Received: " + output.getHistory().getHistoryItem().size() + "elements:");
System.out.println("-----------------------");
for(int i=0;i<output.getHistory().getHistoryItem().size();i++) {
HistoryItem it = output.getHistory().getHistoryItem().get(i);
System.out.println("#" + i + ": id=" + it.getId() + ", type=" + it.getType().value());
}
System.out.println("Check 3 history items");
//Assert.assertEquals(3, output.getHistory().getHistoryItem().size());
HistoryItem it1 = output.getHistory().getHistoryItem().get(0);
HistoryItem it2 = output.getHistory().getHistoryItem().get(1);
HistoryItem it3 = output.getHistory().getHistoryItem().get(2);
/*Assert.assertEquals(Type.QUMQ, it1.getType());
Assert.assertEquals(161L, it1.getId());
Assert.assertEquals(Type.SUM, it2.getType());
Assert.assertEquals(652L, it2.getId());
Assert.assertEquals(Type.L_1_Q, it3.getType());
Assert.assertEquals(13742L, it3.getId());*/
}
public static void main(String[] args) {
ServiceTest test = new ServiceTest();
try {
test.initService();
test.historyTest();
} catch(Exception e ){
e.printStackTrace();
}
}
}
Soap Handler:
package test;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.util.Set;
/**
* <strong>Project: TODO: project name</strong><br/>
* <b>Url:</b> TODO: url<br/>
* <b>Date:</b> 16.05.14<br/>
* <b>Time:</b> 0:48 <br/>
* Copyright(C) 2014 IT Service Plus <br/>
* <b>Description:</b><br/>
* TODO: description
*/
public class CustomSoapHandler implements SOAPHandler<SOAPMessageContext> {
private static final String AUTH_PREFIX = "wsse";
private static final String AUTH_NS =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
private String username;
private String password;
public CustomSoapHandler(String username, String password) {
this.username = username;
this.password = password;
}
public boolean handleMessage(SOAPMessageContext context) {
try {
SOAPEnvelope envelope =
context.getMessage().getSOAPPart().getEnvelope();
SOAPFactory soapFactory = SOAPFactory.newInstance();
SOAPElement wsSecHeaderElm =
soapFactory.createElement("Security", AUTH_PREFIX, AUTH_NS);
Name wsSecHdrMustUnderstandAttr =
soapFactory.createName("mustUnderstand", "S",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
wsSecHeaderElm.addAttribute(wsSecHdrMustUnderstandAttr, "1");
SOAPElement userNameTokenElm =
soapFactory.createElement("UsernameToken", AUTH_PREFIX,
AUTH_NS);
Name userNameTokenIdName =
soapFactory.createName("id", "wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
userNameTokenElm.addAttribute(userNameTokenIdName,
"UsernameToken-ORbTEPzNsEMDfzrI9sscVA22");
SOAPElement userNameElm =
soapFactory.createElement("Username", AUTH_PREFIX, AUTH_NS);
userNameElm.addTextNode(username);
SOAPElement passwdElm =
soapFactory.createElement("Password", AUTH_PREFIX, AUTH_NS);
Name passwdTypeAttr = soapFactory.createName("Type");
passwdElm.addAttribute(passwdTypeAttr,
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
passwdElm.addTextNode(password);
userNameTokenElm.addChildElement(userNameElm);
userNameTokenElm.addChildElement(passwdElm);
wsSecHeaderElm.addChildElement(userNameTokenElm);
if (envelope.getHeader() == null) {
SOAPHeader sh = envelope.addHeader();
sh.addChildElement(wsSecHeaderElm);
} else {
SOAPHeader sh = envelope.getHeader();
sh.addChildElement(wsSecHeaderElm);
}
} catch (Throwable e) {
e.printStackTrace();
}
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
#Override
public void close(MessageContext context) {
//To change body of implemented methods use File | Settings | File Templates.
}
#Override
public Set<QName> getHeaders() {
return null;
}
}
The main reason for your error is incompatible JAXB implementation classes:
aused by: java.lang.ClassCastException: com.ibm.xml.xlxp2.jaxb.JAXBContextImpl incompatible with com.sun.xml.internal.bind.api.JAXBRIContext
Probably the best way to fix this is packaging your own version of JAXB within your application(inside the lib folder) and than change the class loader from WebSphere to be Parent Last.
After that, restart and try it again. If still doesn't work you can try adding your JAXB implementation libraries directly to the Application Server classloader. You can do that creating a directory under $WEBSPHERE_HOME/AppServer/classes and placing your JAXB implementation classes there. Be aware that this approach adds the dropped jars to all WebSphere instances running using this binary codebase.
You can learn more about WebSphere classloaders.
Hope this helps.
How to mock an object that implements an interface and methods not belonging to the latter? I need aplicacaoPT to implement BindingProvider and buscaAplicacaoPorCodigo. The cast works but the buscaAplicacaoPorCodigo call gives a MissingMethodException. I tried with a map and an Expando:
import static org.junit.Assert.*
import grails.test.mixin.*
import grails.test.mixin.support.*
import org.junit.*
import javax.xml.ws.BindingProvider
#TestMixin(GrailsUnitTestMixin)
class CatalogClientServiceTests {
void testFetch() {
AplicacaoSoapService.metaClass.getAplicacaoSoapPort = {
[ getRequestContext: { new HashMap<String, Object>() },
buscaAplicacaoPorCodigo: { String appCode -> "carrapato!" } ] as BindingProvider
}
def applicationDataFromCatalog = service.fetch("dino")
}
void testFetchFailsWithInvalidApplicationCode() {
AplicacaoSoapService.metaClass.getAplicacaoSoapPort = {
def aplicacaoSoapPort = new Expando()
aplicacaoSoapPort.getRequestContext = { new HashMap<String, Object>() }
aplicacaoSoapPort.buscaAplicacaoPorCodigo = { String appCode -> "castanha!" }
aplicacaoSoapPort as BindingProvider
}
shouldFail(IllegalArgumentException) { service.fetch("dino") }
}
}
import javax.xml.ws.BindingProvider
class CatalogClientService {
def aplicacaoPT = new AplicacaoSoapService().getAplicacaoSoapPort()
def grailsApplication
def fetch(String appCode) {
Map<String, Object> req_ctx = ((BindingProvider)aplicacaoPT).getRequestContext();
req_ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, grailsApplication.config.catalogAppEndPointAddress);
def response = aplicacaoPT.buscaAplicacaoPorCodigo(appCode)
println "response: $response"
}
}
I also tried adding buscaAplicacaoPorCodigo to BindingProvider's metaclass but it sticks with one of the implementations for all tests. In the example below response will be printed (above) either "castanha!" or "carrapato!" on both tests for each run.
import static org.junit.Assert.*
import grails.test.mixin.*
import grails.test.mixin.support.*
import org.junit.*
import javax.xml.ws.BindingProvider
#TestMixin(GrailsUnitTestMixin)
class CatalogClientServiceTests {
void testFetch() {
BindingProvider.metaClass.buscaAplicacaoPorCodigo = { String appCode -> "carrapato!" }
AplicacaoSoapService.metaClass.getAplicacaoSoapPort = {
[ getRequestContext: { new HashMap<String, Object>() } ] as BindingProvider
}
def applicationDataFromCatalog = service.fetch("dino")
}
void testFetchFailsWithInvalidApplicationCode() {
BindingProvider.metaClass.buscaAplicacaoPorCodigo = { String appCode -> "castanha!" }
AplicacaoSoapService.metaClass.getAplicacaoSoapPort = {
def aplicacaoSoapPort = new Expando()
aplicacaoSoapPort.getRequestContext = { new HashMap<String, Object>() }
aplicacaoSoapPort as BindingProvider
}
shouldFail(IllegalArgumentException) { service.fetch("dino") }
}
}
I stripped parts of the code above for the sake of simplicity.
I hope some of may help me! :)
I have zero experience with grails, but this seems a problem related with proxies. The resulting proxy doesn't have the buscaAplicacaoPorCodigo available.
AFAIK, you have two choices: either create a interface Buscador, with buscaAplicacaoPorCodigo, and create a super interface for both BindingProvider and Buscador, or, for a pure dynamic solution, metaClass the resulting proxied expando:
I mocked some of your classes, hope I got it right.
BindingProvider.groovy:
interface BindingProvider {
def getRequestContext()
}
And the rest:
class AplicacaoSoapService {
static BindingProvider getAplicacaoSoapPort() {
assert false, "Nope, must be mocked"
}
}
AplicacaoSoapService.metaClass.static.getAplicacaoSoapPort = {
def e = new Expando(
getRequestContext: { [:] }) as BindingProvider
e.getMetaClass().buscaAplicacaoPorCodigo = { String a -> "amendoa!" }
e
}
def provider = AplicacaoSoapService.aplicacaoSoapPort
assert provider.buscaAplicacaoPorCodigo("pudim") == "amendoa!"
Total 'testing newbie' wanting to test the addJsFile method of my custom TagLib. What am I missing?
TagLib:
import com.company.group.application.helper.Util
...
class MyTagLib {
static namespace = 'mytag'
def util
...
def addJsFile = {
if (util.isSecureRequest(request)) {
out << '<script src="https://domain.com/jsfile.js"></script>'
} else {
out << '<script src="http://domain.com/jsfile.js"></script>'
}
}
}
Test (as far as I could get):
import org.springframework.http.HttpRequest
import com.company.group.application.helper.Util
#TestFor(MyTagLib)
class MyTagLibTests {
def util
...
void testAddJsFileSecure() {
def mockUtil = mockFor(Util)
mockUtil.demand.isSecureRequest() { HttpRequest request -> true }
def jsCall = applyTemplate('<mytag:addJsFile />')
assertEquals('<script src="https://domain.com/jsfile.js"></script>', jsCall)
}
void testAddJsFileNotSecure() {
def mockUtil = mockFor(Util)
mockUtil.demand.isSecureRequest() { HttpRequest request -> false }
def jsCall = applyTemplate('<mytag:addJsFile/>')
assertEquals('<script src="http://domain.com/jsfile.js"></script>', jsCall)
}
}
Util isSecureRequest
boolean isSecureRequest(request) {
return [true or false]
}
Error
org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException: Error executing tag <mytag:addJsFile>: Cannot invoke method isSecureRequest() on null object
You need to set the mocked util in tagLib in order to use it.
void testAddJsFileSecure() {
def mockUtilControl = mockFor(Util)
mockUtilControl.demand.isSecureRequest() { HttpRequest request -> true }
//"tagLib" is the default bind object provided
//by the mock api when #TestFor is used
tagLib.util = mockUtilControl.createMock()
//Also note mockFor() returns a mock control
//which on createMock() gives the actual mocked object
def jsCall = applyTemplate('<mytag:addJsFile />')
assertEquals('<script src="https://domain.com/jsfile.js"></script>', jsCall)
//In the end of test you can also verify that the mocked object was called
mockUtilControl.verify()
}
You would not need def util in the test then.
I have TagLib, Service and TestCase as follows
How to mock a service in a taglib to get expected result from service
TagLib:
class SampleTagLib {
static namespace = "sample"
def baseService
def writeName = { attrs, body ->
def result = baseService.findAttributeValue(attrs.something)
if(result)
out << body()
}
}
Service:
class BaseService {
def findAttributeValue(arg1) {
return false
}
}
TagLibUnitTestCase:
import spock.lang.*
import grails.plugin.spock.*
import org.junit.*
import grails.test.mixin.*
import grails.test.mixin.support.*
import grails.test.mixin.Mock
#TestFor(SampleTagLib)
#Mock(BaseService)
class SampleTagLibSpec extends Specification {
def template
def setup(){
tagLib.baseService = Mock(BaseService)
}
def 'writeName'(){
given:
tagLib.baseService.findAttributeValue(_) >> true
def template ='<sample:writeName something='value'>output</sample:writeName>'
when: 'we render the template'
def output = applyTemplate(template, [sonething:'value')
then: 'output'
output =="output"
}
}
But it getting Error condition not satisfied. Getting output = " "
Expected output = "output"
You need to use the grails mockFor to mock out the service.
See Mocking Collaborators
Untested Example:
def strictControl = mockFor(BaseService)
strictControl.demand.findAttributeValue(1..1) { arg1 -> return true }
taglib.baseService = strictControl.createMock()