How can I use relative paths to external response files for soapUI MockService

28,917

Solution 1

I'm not familiar with Groovy, but I assume the File is a normal java.io.File instance.

Relative paths are interpreted as being relative to the application's current directory. Try something like the following to verify:

def defaultPathBase = new File( "." ).getCanonicalPath()
println "Current dir:" + defaultPathBase

If this is the case here, then you may want to use the new File(String parent, String child) constructor, passing your resource directory as the first argument and the relative path as the second.

For example:

// hardcoded for demonstration purposes
def pathbase = "/Users/chet"
def content = new File(pathbase, "Desktop/sample.txt").text

println content

Here's the result of executing the script:

Chets-MacBook-Pro:Desktop chet$ groovy sample.groovy 
This is a sample text file.

It will be displayed by a Groovy script.
Chets-MacBook-Pro:Desktop chet$ groovy sample.groovy 
This is a sample text file.

It will be displayed by a Groovy script.

Chets-MacBook-Pro:Desktop chet$ 

Solution 2

You could have also done the following to get the value of projectDir:

    def projectDir = context.expand('${projectDir}');
Share:
28,917
Mark
Author by

Mark

Senior Software Engineer at EBSCO Information Services

Updated on July 09, 2022

Comments

  • Mark
    Mark almost 2 years

    What I've Done

    I am using soapUI (3.6.1 Free version) mock services to serve up specific data to 2 client applications I am testing. With some simple Groovy script I've set up some mock operations to fetch responses from specific files based on the requests made by the client applications.

    The static contents of the mock response is:

    ${responsefile}
    

    The groovy in the operation dispatch scripting pane is:

    def req = new XmlSlurper().parseText(mockRequest.requestContent)
    if (req =~ "CategoryA")
    {
        context.responsefile = new File("C:/soapProject/Test_Files/ID_List_CategoryA.xml").text
    }
    else
    {
        context.responsefile = new File("C:/soapProject/Test_Files/ID_List_CategoryB.xml").text
    }
    

    In this example, when the client application issues a request to the mock service that contains the string CategoryA, the response returned by soapUI is the contents of file ID_List_CategoryA.xml

    What I'm Trying To Achieve

    This all works fine with the absolute paths in the groovy. Now I want to pull the whole collection of soapUI project file and external files into a package for easy re-deployment. From my reading about soapUI I hoped this would be as easy as setting the project Resource Root value to ${projectDir} and changing my paths to:

    def req = new XmlSlurper().parseText(mockRequest.requestContent)
    if (req =~ "CategoryA")
    {
        context.responsefile = new File("Test_Files/ID_List_CategoryA.xml").text
    }
    else
    {
        context.responsefile = new File("Test_Files/ID_List_CategoryB.xml").text
    }
    

    ... keeping in mind that the soapUI project xml file resides in C:/soapProject/

    What I've Tried So Far

    So, that doesn't work. I've tried variations of relative paths:

    • ./Test_Files/ID_List_CategoryA.xml
    • /Test_Files/ID_List_CategoryA.xml
    • Test_Files/ID_List_CategoryA.xml

    One post indicated that soapUI might consider the project files parent directory as the root for the purposes of the relative path, so tried the following variations too:

    • ./soapProject/Test_Files/ID_List_CategoryA.xml
    • /soapProject/Test_Files/ID_List_CategoryA.xml
    • soapProject/Test_Files/ID_List_CategoryA.xml

    When none of that worked I tried making use of the ${projectDir} property in the groovy script, but all such attempts failed with a "No such property: mockService for class: Script[n]" error. Admittefly, I was really fumbling around when trying to do that.

    I tried using information from this post and others: How do I make soapUI attachment paths relative?

    ... without any luck. Replacing "test" with "mock," (among other changes), in the solution code from that post resulted in more property errors, e.g.

    testFile = new File(mockRunner.project.getPath())
    

    .. led to...

    No such property: mockRunner for class: Script3
    

    What I Think I Need

    The posts I've found related to this issue all focus on soapUI TestSuites. I really need a solution that is MockService centric or at least sheds some light on how it can be handled differently for MockServices as opposed to TestSuites.

    Any help is greatly appreciated. Thanks. Mark.

    The Solution - Provided by GargantuChet

    The following includes the changes suggested by GargantuChet to solve the problem of trying to access the ${projectDir} property and enable the use of relative paths by defining a new projectDir object within the scope of the groovy script:

    def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
    def projectDir = groovyUtils.projectPath
    
    def req = new XmlSlurper().parseText(mockRequest.requestContent)
    if (req =~ "CategoryA")
    {
        context.responsefile = new File(projectDir, "Test_Files/ID_List_CategoryA.xml").text
    }
    else
    {
        context.responsefile = new File(projectDir, "Test_Files/ID_List_CategoryB.xml").text
    }
    
  • Mark
    Mark over 11 years
    Trying your hard coded example for kicks resulted in the following error: Failed to dispatch using script; groovy.lang.MissingMethodException: No signature of method: Script27.var() is applicable for argument types: (java.lang.String) values: [C:/soapProject] Possible solutions: wait(), run(), run(), every(), any(), wait(long)
  • Mark
    Mark over 11 years
    Sorry about Reposts. Didn't realize formatting in comment responses would be so troublesome. As soapUI doesn't have console viewer, I changed your first suggestion to log the defaultPathBase: log.info "Current dir:" + defaultPathBase. As you suspected, it logged the soapUI application directory. Then I tried to see if I could log the value of the ${projectDir} property: log.info "Project dir: " + projectDir I get the following error: Failed to dispatch using script; groovy.lang.MissingPropertyException: No such property: projectDir for class: Script26
  • GargantuChet
    GargantuChet over 11 years
    projectDir might not be defined in the current script / scope. Apparently you can reference it using [def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context); def projectDir = groovyUtils.projectPath; log.info(projectDir)][1], which is probably the Groovy-approved method. I'll grab a copy of Groovy and figure out what's wrong with the hard-coded example. [1]webservices-testing.com/2011/10/…
  • GargantuChet
    GargantuChet over 11 years
    Doh! def, not var. That's what I get for writing code in a language I don't know. I'll edit the answer with a real (hardcoded) example and results.
  • Mark
    Mark over 11 years
    Nice! Using [def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context); def projectDir = groovyUtils.projectPath; log.info(projectDir)] solved my problem. I'll update the "Question" above with the complete solution to format it nicely and make sure to give you the credit :). Thanks a million Chet.
  • Lars Nordin
    Lars Nordin almost 10 years
    This won't work in a project load script "step" - only "log" and "project" objects are available.
  • Lars Nordin
    Lars Nordin almost 10 years
    Updating my comment: it will work if you call: def context = project.getContext() and then run the above.