How to access Body param when MockFor HTTPBuilder - groovy

I am writing test that mocks HTTPBuilder. Here is method call that uses the HTTBuilder
def http = new HTTPBuilder('http://localhost:8010')
public registerUpdate(Long id, Long version){
try{
http.request(Method.POST, JSON){ req ->
body = [
version: version,
id: id
]
response.success = {resp, json ->
log.warn "cached object id: $id and version: $version; status code: " + resp.statusLine.statusCode
}
}
}catch(Exception e){
log.warn('Failure Initiate Connection with Node Driver: ' + e.message);
}
In the test, i ensure that proper method, contentType and the body parameter is set accordingly.
def "some test"(){
setup:
def httpBuildMock = new MockFor(HTTPBuilder.class)
httpBuildMock.demand.request{
met, type, body ->
assert met == Method.POST
assert type == ContentType.JSON
assert 10 == body.version
// def resp = body.call(null)
}
def mockService = httpBuildMock.proxyInstance()
service.http = mockService
when:
service.registerUpdate(1,2)
then:
httpBuildMock.verify mockService
In this test, the assertion for the body.version doesn't work. it gives 'missingPropertyException'. In debug mode, i can see that body parameter has properties 'id' and 'version' but still gives exception. How do i assert for 'body' parameter? Thank You

def "ensure params passed in correctly"(){
setup:
def httpBuildMock = new MockFor(HTTPBuilder.class)
def reqPar = []
def success
def requestDelegate = [
response: [:]
]
httpBuildMock.demand.request(1){
Method met, ContentType type, Closure b ->
b.delegate = requestDelegate
b.call()
reqPar << [method: met, type: type, id: b.body.id, ver: b.body.version ]
}
when:
httpBuildMock.use{
service.registerUpdate(id,ver)
}
then:
assert reqPar[0].method == Method.POST
assert reqPar[0].type == ContentType.JSON
assert reqPar.ver[0] == ver
assert reqPar.id[0] == id
}
For more, please, see my post Mock Httpbuilder and POST Requests in Grails

Related

In Groovy/Spock assert call methods are not executed

In Groovy Unit Test with Spock the following task is quite common:
assert myResult == calculateExpectedResult() (With or without the assert keyword.)
The groovy assert prints out lots of infomation on what is going on here and why my assertion failed. But when the compared objects are very complex and deep it can be tricky go get the concrete property that failed the test.
For this I found the Javers Framework that does an excellent Job comparing the objects and producing an exact diff. I created a trait to do this:
trait DiffTrait {
Javers javers = JaversBuilder.javers().build()
String diff(result, expected) {
Diff diff = javers.compare(result, expected);
def valueChanges = diff.getChangesByType(ValueChange)
String message = ""
valueChanges.each { message += "\n$it.propertyName = $it.left instead of expected: $it.right" }
return message
}
}
Now I can use it in my Unit Tests like this:
def expected = calculateExpectedResult()
assert myResult == expected, diff(myResult, expected)
This way I get a nicely printed list of differences.
But this is kind of verbose because I have to specify the values two times.
So I have changed the trait like this:
trait DiffTrait {
Javers javers = JaversBuilder.javers().build()
def result
def expected
String diff(result, expected) {
Diff diff = javers.compare(result, expected);
def valueChanges = diff.getChangesByType(ValueChange)
String message = ""
valueChanges.each { message += "\n$it.propertyName = $it.left instead of expected: $it.right" }
return message
}
String diff() {
diff(result, expected)
}
def result(result) {
this.result = result
return result
}
def expected(expected) {
this.expected = expected
return expected
}
}
The idea was to use it like this:
def result = callTheSystemToProduceTheRealResult()
def expected = calculateExpectedResult()
assert result(myResult) == expected(expected), diff()
But surprisingly this does not work! The two attributes are null and the diff Method fails with a NotNull-Exception. If I debug this code the expected/result methods are never called!
If I rewrite the code like this
def result = result(callTheSystemToProduceTheRealResult())
def expected = expected(calculateExpectedResult())
assert myResult == expected, diff()
everything works as expected. The methods get called correctly and the attributes are set.
My question is: Why can't I call these methods in the assert statement? What is the difference from the Groovy/Spock perspective of these two code fragements?
Here is a gist containing all the code as running example.
It is quite easy to explain. Assertion message is evaluated before the assertion itself. The following piece of code works perfectly, however it displays static diff message:
import org.javers.core.Javers
import org.javers.core.JaversBuilder
import org.javers.core.diff.Diff
import org.javers.core.diff.changetype.ValueChange
import spock.lang.Specification
class LolSpec extends Specification implements DiffTrait {
def 'lol'() {
expect:
def whatIGot = new Lol(l: 'a')
def whatIExpected = new Lol(l: 'b')
assert result(whatIGot) == expected(whatIExpected), 'diff'
}
}
trait DiffTrait {
Javers javers = JaversBuilder.javers().build()
def result
def expected
String diff() {
diff(result, expected)
}
String diff(result, expected) {
Diff diff = javers.compare(result, expected);
def valueChanges = diff.getChangesByType(ValueChange)
String message = ""
valueChanges.each { message += "\n$it.propertyName = $it.left instead of expected: $it.right" }
return message
}
def result(result) {
this.result = result
return result
}
def expected(expected) {
this.expected = expected
return expected
}
}
class Lol {
String l
}
You need to pass the arguments twice or change the implementation, e.g.:
import groovy.transform.EqualsAndHashCode
import org.javers.core.Javers
import org.javers.core.JaversBuilder
import org.javers.core.diff.changetype.ValueChange
import spock.lang.Specification
class LolSpec extends Specification {
def 'lol'() {
expect:
def whatIGot = new Lol(l: 'a')
def whatIExpected = new Lol(l: 'b')
def diff = new Diff(result: whatIGot, expected: whatIExpected)
assert diff.check(), diff.message()
}
}
class Diff {
Javers javers = JaversBuilder.javers().build()
def result
def expected
String message() {
def diff = javers.compare(result, expected);
def valueChanges = diff.getChangesByType(ValueChange)
String message = ""
valueChanges.each { message += "\n$it.propertyName = $it.left instead of expected: $it.right" }
return message
}
boolean check() {
result.equals(expected)
}
}
#EqualsAndHashCode
class Lol {
String l
}

Unable to retrieve data from an xml to place in an array

I am trying to retrieve a number of flightids from an xml and place them in an array but I keep getting no data displayed. It doesn't seem to find 'flights' but I am not sure why, is there anything wrong with the code below?
import groovy.xml.XmlUtil
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def response = context.expand( '${SOAP Request#Response}' )
def parsedxml = new XmlSlurper().parseText(response)
def tests= parsedxml.'**'.findAll { it.name() == 'b:TestId'}
log.info tests
//Get the rate plan codes
def testId = { option ->
def res = option.'**'.findAll {it.name() == 'b:TestId'}
if (res) return option.TestId.text()
null
}
def testIdArray = []
tests.each { if (testId(it)) testIdArray << testId(it) }
for (int i = 0; i < testIdArray.size(); i++) {
log.error "TestIds: " + testIdArray[i]
}
log.warn testIdArray.size()
Below is the xml:
<s:Envelope xxx="xxx" xxx="xxx">
<s:Header>
<a:Action s:mustUnderstand="1">xxx</a:Action>
</s:Header>
<s:Body>
<XML1 xmlns="xxx">
<XML2 xmlns:b="xxx" xmlns:i="xxx">
<XML3>
<b:TestId>000000</b:TestId>
</XML3>
<XML3>
<b:TestId>000000</b:TestId>
</XML3>
</XML2>
</XML1>
</s:Body>
</s:Envelope>
Pass the xml string response to below response variable
def xml = new XmlSlurper().parseText(response)
def getFlightIds = { type = '' ->
type ? xml.'**'.findAll { it.name() == type }.collect { it.FlightId.text() } : xml.'**'.findAll {it.FlightId.text()}
}
//Get the respective flight ids
//Use the desired one as you have mentioned none
def inFlightIds = getFlightIds('InboundFlightInformation')
def outFlightIds = getFlightIds('OutboundFlightInformation')
def allFlightIds = getFlightIds()
log.info "Inbound flight ids: ${inFlightIds}"
log.info "Outbound flight ids: ${outFlightIds}"
log.info "All flight ids: ${allFlightIds}"
You can quickly try online Demo
it.name() in your case it is a NodeChild
so, it.name() returns just a name without prefix. it means you should compare it to FlightId (without b: )
if you want to check a namespace (linked to a prefix) then your lookup must be like this:
def flights = parsedxml.'**'.findAll { it.name() == 'FlightId' && it.namespaceURI()=='xxx' }

Save test case properties if any of the assertions fail

How to save the test case properties if any of the assertions fail within this groovy script step?
Below is example code:
// define properties required for the script to run.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def dataFolder = groovyUtils.projectPath
def vTIDAPI = testRunner.testCase.getPropertyValue("vTIDAPI")
def vTIDDB = testRunner.testCase.getPropertyValue("vTIDDB")
def RefAPI = testRunner.testCase.getPropertyValue("RefAPI")
def RefDB = testRunner.testCase.getPropertyValue("RefDB")
def AmountAPI = testRunner.testCase.getPropertyValue("AmountAPI")
def AmountDB = testRunner.testCase.getPropertyValue("AmountDB")
def CurrencyAPI = testRunner.testCase.getPropertyValue("CurrencyAPI")
def CurrencyDB = testRunner.testCase.getPropertyValue("CurrencyDB")
assert vTIDAPI == vTIDDB
assert RefAPI == RefDB
assert AmountAPI == AmountDB
assert CurrencyAPI == CurrencyDB
Here is the Groovy Script which does compare the given set of properties and on any of the assertion failure, writes the properties to a given file.
You need to change the value of property file name to be stored for variable propFileName variable.
Add more properties to be asserted in the form of key:value pairs format if needed
//Provide / edit the file name to store properties
def propFileName = '/tmp/testCase.properties'
//Define the properties to be matched or asserted ; add more properties if needed
def props = [ 'vTIDAPI':'vTIDDB', 'RefAPI':'RefDB', 'AmountAPI': 'AmountDB', 'CurrencyAPI': 'CurrencyDB']
/**
* Do not edit beyond this point
*/
def writeTestCasePropertiesToFile = {
//Get the test case properties as Properties object
def properties = context.testCase.properties.keySet().inject([:]){map, key -> map[key] = context.testCase.getPropertyValue(key); map as Properties}
log.info properties
assert properties instanceof Properties
properties?.store(new File(propFileName).newWriter(), null)
}
def myAssert = { arg1, arg2 ->
context.testCase.getPropertyValue(arg1) == context.testCase.getPropertyValue(arg2) ? null : "${arg1} value does not match with ${arg2}"
}
def failureMessage = new StringBuffer()
props.collect{ null == myAssert(it.key, it.value) ?: failureMessage.append(myAssert(it.key, it.value)).append('\n')}
if(failureMessage.toString()) {
log.error "Assertion failures:\n ${failureMessage.toString()}"
writeTestCasePropertiesToFile()
throw new Error(failureMessage.toString())
} else {
log.info 'Assertions passed'
}
EDIT: Based on the OP comments
Replace def myAssert = ... with below code fragment.
def myAssert = { arg1, arg2 ->
def actual = context.testCase.getPropertyValue(arg1)
def expected = context.testCase.getPropertyValue(arg2)
actual == expected ? null : "${arg1} value does not match with ${arg2} - api ${actual} vs db ${expected}"
}

Hit a URL using groovy step

I created a HTTP request step and checked the response code 200/400 .
The same i want to check using groovy only. No HTTP requeststep. Use only groovy step.
URL response script:-
def rawResponse = new String(testRunner.testCase.testSteps["HTTP Request"].testRequest.response.rawResponseData)
log.info rawResponse
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def httpResponseHeaders = context.testCase.testSteps["HTTP Request"].testRequest.response.responseHeaders
def httpStatus = httpResponseHeaders["#status#"]
def httpStatusCode = (httpStatus =~ "[1-5]\\d\\d")[0]
log.info("HTTP status code: " + httpStatusCode)
if (httpStatusCode == "200")
{
log.info "Success"
}
else
{
log.info "Failure"
}

Result of Replaced/Overriden Parameterless Method Not Passed to the Constructor

I'm trying to change the behaviour of the constructor of a groovy class by replacing a method in that class which is used to set a property but the properties are not getting set with the expected values.
class TestClass {
def noParam
def withParam
TestClass() {
noParam = noParam()
withParam = withParam('second test')
}
def noParam() {
return 'first test'
}
def withParam(param) {
return param
}
}
TestClass.metaClass.withParam = { param -> 'pass' }
TestClass.metaClass.noParam = {-> 'pass' }
def test = new TestClass()
assert test.withParam('dummy') == 'pass' //passes
assert test.withParam == 'pass' // fails
assert test.noParam() == 'pass' // passes
assert test.noParam == 'pass' // fails
Groovy is not using your metaclass overrides in the TestClass constructor when it executes the noParam and withParam methods. In fact, if you type the parameter in your withParam method, the 2nd assert will also fail.
class TestClass {
def noParam
def withParam
TestClass() {
noParam = noParam()
withParam = withParam('second test')
println "in the constructor: noParam = $noParam, withParam = $withParam"
}
def noParam() {
return 'first test'
}
def withParam(String param) {
return param
}
}
TestClass.metaClass.withParam = { String param -> 'pass' }
TestClass.metaClass.noParam = {-> 'pass' }
def test = new TestClass()
assert test.withParam('dummy') == 'pass'
assert test.withParam == 'pass' // this fails now too!
assert test.noParam() == 'pass'
assert test.noParam == 'pass' // this fails
Here's the output: in the constructor: noParam = first test, withParam = second test
test.withParam and test.noParam are actually calling test.getWithParam() and test.getNoParam() - they are returning the property values set in the constructor.
test.withParam('dummy') and test.noParam() are calling your metaclass method and returning "pass".
As far as why groovy does not use the metaclass method in your constructor, I'm not sure... I couldn't find anything in the metaclass documentation...
Maybe you could use static methods instead?
class TestClass {
def noParam
def withParam
TestClass() {
noParam = TestClass.noParam()
withParam = TestClass.withParam('second test')
println "in the constructor: noParam = $noParam, withParam = $withParam"
}
static def noParam() {
return 'first test'
}
static def withParam(String param) {
return param
}
}
TestClass.metaClass.'static'.withParam = { String param -> 'pass' }
TestClass.metaClass.'static'.noParam = {-> 'pass' }
def test = new TestClass()
assert test.withParam('dummy') == 'pass'
assert test.withParam == 'pass' // passes!
assert test.noParam() == 'pass'
assert test.noParam == 'pass' // passes!
Here's the output: in the constructor: noParam = pass, withParam = pass

Resources