I am not able to get the Groovy MarkupBuilder to work with soapUI. I am very new to Groovy and I am just following one of the user guides on creating XML.
Testing a very simple method:
public String Example(){
def writer = new StringWriter()
def root = new MarkupBuilder(writer)
root.mkp.xmlDeclaration(version:"1.0", encoding:"UTF-8")
root.Root{
Example("A")
}
return writer.toString()
}
I get the following error in soapUI: ava.lang.NoClassDefFoundError: MockXML$_Example_closure2
I have no error when I run from Groovy Console.
In the same class I have:
public String Hello(){
return "Hello"
}
Which works fine in soapUI.
Is there something I would need setup/imported/configured in soapUI that I am not thinking about to handle MarkupBuilder/closures?
Thanks
I believe you have a syntax error in your markup. I think:
root.Root {
should be:
root.Root() {
I think the Groovy evaluating your Root element as a closure instead of a new element in the markup.
Related
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 }
So Ive got a Grails 3.2.3 app, and in one of the services, I am loading a WSDL located in the root of my project folder to use with a SOAPClient like so:
def wsdl = "soap.wsdl"
SOAPClient soapClient
#PostConstruct
void init() {
soapClient = new SOAPClient(wsdl)
}
My spock test is annotated with #MockFor(MyService) and Ive checked that the test runs the init method fine.
Now when the app is running, this creates the SOAPClient just fine, but when trying to write a Spock test, new SOAPClient(wsdl)returns null. Im guessing this is because when running the Spock test, the wsdl isnt properly in the classpath, but I havent found a way to solve this. Any ideas please?
If it were me, I would metaClass the constructor of SOAPClient to return a mock of SOAPClient. Something like this:
def 'test something'(){
setup:
def soapClientMock = Mock(SOAPClient)
SOAPClient.metaclass.constructor = {String filename ->
assert filename == "soap.wsdl"
return soapClientMock
}
}
I was trying to mock the following REST web-service using soapUI
Sample Request:
<Request>
<HistoricTxn>
<reference>E1</reference>
<method>txn</method>
</HistoricTxn>
</Request>
SampleResponse1
<Response>
<reason>ACCEPTED</reason>
<status>1</status>
<time>10:12</time>
</Response>
SampleResponse2
<Response>
<information>Failure on invalid request details</information>
<reason>fails Luhn check</reason>
<status>3</status>
<time>10:15</time>
</Response>
Usually I use this kind of a groovy script to evaluate the request and out put a dynamic response. (When using soapUI to mock SOAP web services)
groovy Script:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
def holder = groovyUtils.getXmlHolder(mockRequest.getRequestContent());
def reference = holder.getNodeValue("//reference");
if(reference == "Success"){
return "SampleResponse1";
} else {
return "SampleResponse2";
}
Unfortunately when I try to hit a request to this REST mock service end point it returns an error.
Error:
com.eviware.soapui.impl.wsdl.mock.DispatchException: Failed to
dispatch using script; java.lang.NullPointerException: Cannot invoke
method getRequestContent() on null object
I understand that the error message says getRequestContent() has returned a null value and because of that I am getting this exception. But the same works with the SOAP mock services, with out returning null values or causing exceptions. Appreciate any workarounds to overcome this issue.
I just figured that mockRequest.getRequestContent() returns null for all the POST, PUT, DELETE requests sent to REST web-services mocked using soapUI (version 5.2.1)
def holder = groovyUtils.getXmlHolder(mockRequest.getRequestContent());
Since the above (RequestContent) returns null, soap UI can not evaluate the value of the following tag.
def reference = holder.getNodeValue("//reference");
SoapUIOfficial References for this bug in soapUI(version 5.2.1):
https://community.smartbear.com/t5/SoapUI-NG/SoapUI-5-0-requestContent-is-null-for-Rest-Mock-service/td-p/40458
https://community.smartbear.com/t5/SoapUI-NG/Mock-Service-mockRequest-requestContent-is-NULL-HTTP-PUT/td-p/42138
I just found a workaround to overcome the aforesaid bug in soapUI(version 5.2.1).
By this point it is clear to me that I can use mockRequest.getRequest().getReader().readLine() script to read a single line in the request body. (though mockRequest.getRequestContent() returned a null object)
I would simply access the request body using the following groovy script.
def requestBody="";
try {
while ((line = mockRequest.getRequest().getReader().readLine()) != null){
requestBody = requestBody+line;
}
} catch (Exception e) {
log.error("exception:"+e)
}
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
def holder = groovyUtils.getXmlHolder(requestBody);
def reference = holder.getNodeValue("//reference");
According to the above script, it will have to read the request body line by line and then merge all the lines to have the whole request body.
Since the request body is not null anymore following script can evaluate the value inside reference tag.
def reference = holder.getNodeValue("//reference");
eventually i was able to mock my REST mock service with dynamic responses according to following conditions.
if(reference == "Success"){
return "SampleResponse1";
} else {
return "SampleResponse2";
}
Hope you could save a lot of time by following this method.
I have been trying to figure this out for 2 days now and I am really stuck and frustrated. I have a domain object with a service which is being used for custom validation. The domain looks like this:
class Llama {
String name
transient myFetcherService
static transients = [
'myFetcherService'
]
static constraints = {
name validator: { val, obj ->
if (obj.nameExists(val) == true) {
//return some error here.
}
}
}
protected boolean nameExists(String name) {
List<Llama> llamasList = myFetcherService.fetchExistingLlamasByName(name)
if (llamasList.isEmpty()) {
return false
}
return true
}
}
Now, I have another Service, which simply saves a list of Llama objects. It looks like this:
class LlamaFactoryService {
public void createLlamas(List<String> llamaNames) {
llamaNames.each { name ->
new Llama(name: name).save()
}
}
}
In my test. I keep getting this error:
Failure: createLlamas should create Llammas (com.myLlamaProject.LlamaFactoryServiceSpec)
| java.lang.NullPointerException: Cannot invoke method myFetcherService on null object
I don't understand. In my tests, added a metaClass for the service in the "given" section. When it tries to save, it's telling that the service is null. This is what my test looks like:
given:
def myFetcherService = mockFor(MyFetcherService)
myFetcherService.demand.fetchExistingLlamasByName {def name -> return []}
Llama.metaClass.myFetcherService = myFetcherService.createMock()
when:
service.createLlamas(['Pablo','Juan','Carlos'])
then:
//some validations here....
I also tried using metaClass on the method nameExists() like:
Llama.metaClass.myFetcherService = { def name -> false }
, but it gives me the same nullPointerException as the one above. Could someone point me to the right direction? I'm a bit stuck. :(
Thanks in advance for reading and helping.
You're using a unit test and the general rule for unit tests is that beans generally aren't created for you, so you'll need to inject them yourself.
(Code edited to reflect the fact I misread the question)
I think you want a testing pattern something like:
given:
def mockMyFetcherService = Mock(MyFetcherService) // create the mock
Llama.metaClass.getMyFetcherService = { mockMyFetcherService } // inject the dependency
def returnList = [] // let's just define this here and you can re-use this pattern in other tests more easily
when:
service.createLlamas(['Pablo','Juan','Carlos'])
then:
// tell Spock what you expect to have happen with your Mock - return the List you defined above
3 * mockFetcherService.fetchExistingLlamasByName(_) >> returnList
If the injection of the service into the metaClass doesn't work (suggested here), you could always try using the defineBeans{} closure within the unit test itself (http://www.block-consult.com/blog/2011/08/17/inject-spring-security-service-into-domain-class-for-controller-unit-testing/).
Thus you could try:
defineBeans {
myFetcherService(MockMyFetcherService)
}
where MockMyFetcherService is defined in the same file that defines the test. This is the approach followed here:
See here for examples of more Spock interactions.
If you're using Grails 2.4.3 or below you'll need to put CGLIB in BuildConfig.groovy but I see here that it's already done for you in 2.4.4, so you should be ok just to use Mock(classname).
Let's say I have a simple action in my controller that ends with:
render(contentType: "text/json") {
message = 'some text'
foo = 'bar'
}
It renders correctly, as per the JSON builder documentation. However, when I attempt to unit test that response in a ControllerUnitTest, I get a blank string with controller.response.contentAsString. I even tried controller.renderArgs, but that just contains contentType: "text/json".
When I convert the JSON to a map, and marshall it as JSON, then I can test properly. But is there a way to unit test the code as it stands?
you have to call the action in your tests and compare the results using controller.response.contentAsString
so your test method would look like
void testSomeRender() {
controller.someRender()
assertEquals "jsonString", controller.response.contentAsString
}
Take a look at this blog post http://www.lucasward.net/2011/03/grails-testing-issue-when-rendering-as.html
After much searching, I found that this is not possible in 1.3.7. Either have to upgrade to Grails 2.0, or override the controller metaClass as suggested in this post:
controller.class.metaClass.render = { Map map, Closure c ->
renderArgs.putAll(map)
switch(map["contentType"]) {
case null:
break
case "application/xml":
case "text/xml":
def b = new StreamingMarkupBuilder()
if (map["encoding"]) b.encoding = map["encoding"]
def writable = b.bind(c)
delegate.response.outputStream << writable
break
case "text/json":
new JSonBuilder(delegate.response).json(c)
break
default:
println "Nothing"
break
}
}