Top 1% !
Pearl of Wisdom
Popularity: 267th place
Modified Oct 21, 2014

Published on:

No tags for this snippet yet.

Starting MounteBank stubs from inside gradle

Starting MounteBank stubs from inside gradle:
Copy Embed Code
<iframe id="embedFrame" style="width:600px; height:300px;"
Click on the embed code to copy it into your clipboard Width Height
Leave empty to retrieve all the content Start End
## MounteBank for API stubbing While developing application with external API calls stubs with some logic are mandatory. [MounteBank]( provides bright and simple solution for stubbing HTTP API. It is possible to start MounteBank server directly from command line and initialize its content with folllowing *curl* command: $ mb $ curl -X POST -d@./src/test/groovy/online4m/apigateway/si/test/imposter.json http://localhost:2525/imposters where *imposter.json* file contains configuration of stubs. If you use [gradle]( build subsystem it is vital to start *mb* server directly from *build.gradle* script. ### Configure *build.gradle* with *MounteBank* Running *mb* server requires two steps: * starting the *mb* node.js server * sending the HTTP POST request with imposters configuration - for stubs initialization Starting the server requires new gradle task for starting shell command and waiting for some response from the server itself. #### Add new task definition: **ExecWait** Thanks to this great [post]( let's define new task class. There are a few of attributes: * **command** - command to execute * **ready** - string as part of an output from command that if reachable in output stream, should end ExecWait task execution * **director** - directory where command should be executed * **logOutput** - if set to true and *ready* string is not defined, output from command is logged to the output stream * **requiredActivePort** - if defined on this port some system process should run. If there is no process this task waits up to 6s. class ExecWait extends DefaultTask { String command String ready String directory Boolean logOutput = false Integer requiredActivePort @TaskAction def spawnProcess() { if (requiredActivePort) { boolean running = false for(int i=0; i < 3; i++) { def cmd = "lsof -Fp -i :$requiredActivePort" def process = cmd.execute() { line -> running = true } if (!running) { sleep(2000) } else { break } } } ProcessBuilder builder = new ProcessBuilder(command.split(" ")) builder.redirectErrorStream(true) File(directory)) Process process = builder.start() InputStream stdout = process.getInputStream() BufferedReader reader = new BufferedReader(new InputStreamReader(stdout)) if (ready || logOutput) { println " === OUTPUT" def line while((line = reader.readLine()) != null) { println line if (ready && line.contains(ready)) { println "$command is ready" break } } println " ===" } } } #### Add new task definition: **FreePorts** This task kills processes working on the given port. class FreePorts extends DefaultTask { List ports = [] @TaskAction def freePorts() { println " === FreePorts Task started: $ports" if (!ports) { return } ports.each { port -> def cmd = "lsof -Fp -i :$port" def process = cmd.execute() { line -> def killCmd = "kill -9 ${line.substring(1)}" def killProcess = killCmd.execute() killProcess.waitFor() println " === Process killed on port: $port" } } } } #### Define task to start *MounteBank* server task startMounteBank(type: ExecWait) { command "mb --loglevel info" ready "point your browser to http://localhost:2525" directory "." } #### Define task to initialize *MounteBank* imposters This task requires *MounteBank* server to be accessible, so depends on the *startMounteBank* task. It does not required any *ready* string to check command execution but logs command output. task initImposters(dependsOn: "startMounteBank", type: ExecWait) { command "curl -X POST -d@./src/test/groovy/online4m/apigateway/si/test/imposter.json http://localhost:2525/imposters" directory "." logOutput true } #### Define task to stop *MounteBank* server task stopMounteBank(type: FreePorts) { // port: 2525 - mb (MounteBank), ports = [2525] } #### Define task to run *MounteBank* stubs task runMounteBank(dependsOn: [stopMounteBank, initStubs]) << { description "Start servers required for development: MounteBank (external API stubs), Redis key/value store" } ## Start *MounteBank* as prerequisite to **test** task Before running any test initialize environment, so run server with stubs. When tests are finished clean environment. Shutdown stubs server. test.dependsOn runMounteBank test.finalizedBy stopMounteBank ## PROBLEM: while load testing application that sends requests to *MounteBank*, unexpected resource lock could happen While load testing with, for example, **siege** command, at least on OSX, $ siege -b -c 200 -r 100 -H 'Content-Type: application/json' 'http://localhost:5050/api/call POST < ./src/test/groovy/online4m/apigateway/si/test/testdata.json' unexpected lock on log file resource could happend. As for now I do not have clear answer what is the compelling reason. I'm going to investigate this problem but as for now it is possible to apply the following workaround. Run *MounteBank* server log level set to error, so without logging in fact. To make it working some changes in tasks configuration are required. ### Change logging level to **error** for *MounteBank* When log level is set to error, *MounteBank* server does not produce any output. So ready command should be empty task startMounteBank(type: ExecWait) { command "mb --loglevel error" ready "" directory "." } ### Change imposters initialization task Because *startMounteBank* does not produce *ready* command so we have to wait for it task initImposters(dependsOn: "startMounteBank", type: ExecWait) { command "curl -X POST -d@./src/test/groovy/online4m/apigateway/si/test/imposter.json http://localhost:2525/imposters" directory "." logOutput true requiredActivePort 2525 } Now load tests should work normally.
If you want to be updated about similar snippets, Sign in and follow our Channels