mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.59k stars 1.07k forks source link

Requests only matching once? #421

Closed karl0ss closed 6 years ago

karl0ss commented 6 years ago

I am running this on Node.JS....I have configured my js as follows using a JSON schema matcher -

var mockserver = require('mockserver-node');
var mockServerClient = require('mockserver-client').mockServerClient;
var mockserver_port = 1080;

mockserver
  .start_mockserver({serverPort: mockserver_port, verbose: true})
  .then(
    function () {
      mockServerClient("localhost", 1080).mockAnyResponse({
        "httpRequest": {
          'path': '/test/JSONSCHEMA',
          "body": {
            "jsonSchema": JSON.stringify({
              "$id": "http://example.com/example.json",
              "type": "object",
              "definitions": {},
              "$schema": "http://json-schema.org/draft-06/schema#",
              "properties": {
                "Name": {
                  "$id": "/properties/Name",
                  "type": "string"
                },
                "Number": {
                  "$id": "/properties/Number",
                  "type": "integer"
                }
              }
            })
          }
        },
        "httpResponse": {
          'body': JSON.stringify({name: 'You Sent JSON'}),
        }
      }).then(
        function () {
          console.log("created \"/JSON SCHEMA\" expectation");
        },
        function (error) {
          console.log(error);
        }
      );

    },
    function (error) {
      console.log(JSON.stringify(error));
    }
  );

When I run the server and post the following json via Postman -

POST /test/JSONSCHEMA HTTP/1.1
Host: localhost:1080
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 41050455-0962-ff30-b517-8ef40fc9b481

{
  "Name": "customer",
  "Number": 408401890
}

The first response is a 200 with { "name": "You Sent JSON" }

2018-01-25 14:31:06,581 INFO o.m.m.HttpStateHandler request:

    {
      "method" : "POST",
      "path" : "/test/JSONSCHEMA",
      "body" : {
        "type" : "STRING",
        "string" : "{\n  \"Name\": \"customer\",\n  \"Number\": 408401890\n}",
        "contentType" : "text/plain; charset=utf-8"
      },
      "cookies" : {
        "sessionId" : "2By8LOhBmaW5nZXJwcmludCIlMDAzMW"
      },
      "headers" : {
        "Origin" : [ "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop" ],
        "Cookie" : [ "sessionId=2By8LOhBmaW5nZXJwcmludCIlMDAzMW" ],
        "Cache-Control" : [ "no-cache" ],
        "Accept" : [ "*/*" ],
        "Connection" : [ "keep-alive" ],
        "User-Agent" : [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" ],
        "Host" : [ "localhost:1080" ],
        "Postman-Token" : [ "2d726b23-c7af-0eb5-b2a8-48cb81fb9522" ],
        "Accept-Encoding" : [ "gzip, deflate, br" ],
        "Accept-Language" : [ "en-US,en;q=0.9" ],
        "Content-Length" : [ "47" ],
        "Content-Type" : [ "application/json" ]
      },
      "keepAlive" : true,
      "secure" : false
    }

 matched expectation:

    {
      "path" : "/test/JSONSCHEMA",
      "body" : {
        "type" : "JSON_SCHEMA",
        "jsonSchema" : "{\"$id\":\"http://example.com/example.json\",\"type\":\"object\",\"definitions\":{},\"$schema\":\"http://json-schema.org/draft-06/schema#\",\"properties\":{\"Name\":{\"$id\":\"/properties/Name\",\"type\":\"string\"},\"Number\":{\"$id\":\"/properties/Number\",\"type\":\"integer\"}}}"
      }
    }

2018-01-25 14:31:06,586 INFO o.m.m.HttpStateHandler returning response:

    {
      "headers" : {
        "Content-Type" : [ "application/json; charset=utf-8" ],
        "Cache-Control" : [ "no-cache, no-store" ],
        "connection" : [ "keep-alive" ]
      },
      "body" : "{\"name\":\"You Sent JSON\"}"
    }

 for request:

    {
      "method" : "POST",
      "path" : "/test/JSONSCHEMA",
      "body" : {
        "type" : "STRING",
        "string" : "{\n  \"Name\": \"customer\",\n  \"Number\": 408401890\n}",
        "contentType" : "text/plain; charset=utf-8"
      },
      "cookies" : {
        "sessionId" : "2By8LOhBmaW5nZXJwcmludCIlMDAzMW"
      },
      "headers" : {
        "Origin" : [ "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop" ],
        "Cookie" : [ "sessionId=2By8LOhBmaW5nZXJwcmludCIlMDAzMW" ],
        "Cache-Control" : [ "no-cache" ],
        "Accept" : [ "*/*" ],
        "Connection" : [ "keep-alive" ],
        "User-Agent" : [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" ],
        "Host" : [ "localhost:1080" ],
        "Postman-Token" : [ "2d726b23-c7af-0eb5-b2a8-48cb81fb9522" ],
        "Accept-Encoding" : [ "gzip, deflate, br" ],
        "Accept-Language" : [ "en-US,en;q=0.9" ],
        "Content-Length" : [ "47" ],
        "Content-Type" : [ "application/json" ]
      },
      "keepAlive" : true,
      "secure" : false
    }

 for response action:

    {
      "headers" : {
        "Content-Type" : [ "application/json; charset=utf-8" ],
        "Cache-Control" : [ "no-cache, no-store" ]
      },
      "body" : "{\"name\":\"You Sent JSON\"}"
    }

As expected, but any posts i do after the first one all come back as 404s and do not work, but nothing has changed??

2018-01-25 14:31:42,546 INFO o.m.m.HttpStateHandler no active expectations when receiving request:

    {
      "method" : "POST",
      "path" : "/test/JSONSCHEMA",
      "body" : {
        "type" : "STRING",
        "string" : "{\n  \"Name\": \"customer\",\n  \"Number\": 408401890\n}",
        "contentType" : "text/plain; charset=utf-8"
      },
      "cookies" : {
        "sessionId" : "2By8LOhBmaW5nZXJwcmludCIlMDAzMW"
      },
      "headers" : {
        "Origin" : [ "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop" ],
        "Cookie" : [ "sessionId=2By8LOhBmaW5nZXJwcmludCIlMDAzMW" ],
        "Cache-Control" : [ "no-cache" ],
        "Accept" : [ "*/*" ],
        "Connection" : [ "keep-alive" ],
        "User-Agent" : [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" ],
        "Host" : [ "localhost:1080" ],
        "Postman-Token" : [ "f518fa26-227d-2375-57cf-e60de88ddbb8" ],
        "Accept-Encoding" : [ "gzip, deflate, br" ],
        "Accept-Language" : [ "en-US,en;q=0.9" ],
        "Content-Length" : [ "47" ],
        "Content-Type" : [ "application/json" ]
      },
      "keepAlive" : true,
      "secure" : false
    }

2018-01-25 14:31:42,550 INFO o.m.m.HttpStateHandler no matching expectation - returning:

    {
      "statusCode" : 404,
      "reasonPhrase" : "Not Found"
    }

 for request:

    {
      "method" : "POST",
      "path" : "/test/JSONSCHEMA",
      "body" : {
        "type" : "STRING",
        "string" : "{\n  \"Name\": \"customer\",\n  \"Number\": 408401890\n}",
        "contentType" : "text/plain; charset=utf-8"
      },
      "cookies" : {
        "sessionId" : "2By8LOhBmaW5nZXJwcmludCIlMDAzMW"
      },
      "headers" : {
        "Origin" : [ "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop" ],
        "Cookie" : [ "sessionId=2By8LOhBmaW5nZXJwcmludCIlMDAzMW" ],
        "Cache-Control" : [ "no-cache" ],
        "Accept" : [ "*/*" ],
        "Connection" : [ "keep-alive" ],
        "User-Agent" : [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" ],
        "Host" : [ "localhost:1080" ],
        "Postman-Token" : [ "f518fa26-227d-2375-57cf-e60de88ddbb8" ],
        "Accept-Encoding" : [ "gzip, deflate, br" ],
        "Accept-Language" : [ "en-US,en;q=0.9" ],
        "Content-Length" : [ "47" ],
        "Content-Type" : [ "application/json" ]
      },
      "keepAlive" : true,
      "secure" : false
    }

Any help would be appreciated, kinda pulling my hair out..

UPDATE, I have just done some GET requests tests, and this does the same, the first request works, all the subsequent (repeated) calls all get 404?

jamesdbloom commented 6 years ago

If you want to match expectations multiple time you need to specify the number of times you want to match, as shown in the following example: http://mock-server.com/mock_server/getting_started.html#button_match_request_by_path_exactly_twice

Or create an expectation that responds an unlimited number of times, as follows:

var mockServerClient = require('mockserver-client').mockServerClient;
mockServerClient("localhost", 1080).mockAnyResponse({
    "httpRequest": {
        "path": "/some/path"
    },
    "httpResponse": {
        "body": "some_response_body"
    },
    "times": {
        "unlimited": true
    },
    "timeToLive": {
        "unlimited": true
    }
}).then(
    function () {
        console.log("expectation created");
    },
    function (error) {
        console.log(error);
    }
);
jimkohl commented 6 years ago

James was just going to respond to this one as I ran into same thing awhile ago.
Yes have found specifying the times unlimited: true took care of it and can call as many times as I need to ...

Perhaps you chose the "one shot" default for good reason however I think that the more natural expectation would be to make "unlimited" the default (you don't have to specify it at all) and then if you want to specify a limited number of times it can be invoked, that can be done by specifying "times". What do you think?

jamesdbloom commented 6 years ago

That is an interesting point and I do agree. I look at changing that to avoid the same confusion in the future. The original logic was much more complex and dynamically change from one shot to unlimited in certain situations but that was removed as it was complex to reason about, so I think the once default was a hang over from that. I'm going to re-open this issue until the default is fixed to unlimited.

karl0ss commented 6 years ago

Thanks guys :)

jimkohl commented 6 years ago

James, thats great I think it would be a win for everyone ... Curious why @karl0ss just closed this issue (?) if you changed it to "proposal" status. Maybe I'm just not familiar with this projects workflow yet :). I'd think it would need to be kept open so it can be actioned.

jamesdbloom commented 6 years ago

I have now changed the default to unlimited. This will be available in the next release unless you want to use the snapshot version.

jimkohl commented 6 years ago

Excellent news James! Thanks I'll test it out.

karl0ss commented 6 years ago

Sorry @jimkohl I didn't see the update in the status