javascriptjsonrestpostmantv4

Postman always valid as true a response with the schema using tv4


I've did a lot of tests but I coulnd't find the way to solve it. Simplifying, I have this Postman test script to validate that the JSON response es according with the JSON schema defined to this API:

const stockQuotesSchema = JSON.parse(pm.environment.get("schema"));

pm.test("Stock quote returns 200 OK", function () {
    pm.response.to.have.status(200);
})

pm.test("Stock quote is JSON", function () {
    pm.response.to.be.json;
})

pm.test("Stock quote response matches schema", function () {
    const validationResult = tv4.validateResult(pm.response.json(), stockQuotesSchema);
    pm.expect(validationResult.valid).to.be.true;
})

This is the API schema defined (simplified):

{
    "codexxx": "UNAUTHENTICATED",
    "messagexxx": "token expired"
}

This is the response I get after run the request:

{
    "code": "UNAUTHENTICATED",
    "message": "token expired"
}

As the "code" field and the "message" field doesn't exist in the schema I hope to get a FAIL, but I always retrieve a True.

This is the Postman result image

I need to validate every response with a long JSON schema (I mean bigger schema than the example above). Any idea? Thanks.


Solution

  • You can enforce the proposed (and then removed) banUnknownProperties mode through additional arguments to validateResult as described here. For example:

    const tv4 = require('tv4');
    
    const schema = {
        properties: {
            codexxx: {
              type: 'string'
            },
            messagexxx: {
              type: 'string'
            }
        }
    };
    
    const invalidResponse = {
        code: 'UNAUTHENTICATED',
        message: 'token expired'
    };
    
    const validResponse = {
        codexxx: 'UNAUTHENTICATED',
        messagexxx: 'token expired'
    };
    
    const invalidRelaxedResult = tv4.validateResult(invalidResponse, schema);
    const validRelaxedResult = tv4.validateResult(validResponse, schema);
    const invalidStrictResult = tv4.validateResult(invalidResponse, schema, false, true);
    const validStrictResult = tv4.validateResult(validResponse, schema, false, true);
    
    console.log('Relaxed (invalid):', invalidRelaxedResult.valid);
    console.log('Relaxed (valid):', validRelaxedResult.valid);
    console.log('Strict (invalid):', invalidStrictResult.valid,
                invalidStrictResult.error.message, invalidStrictResult.error.dataPath);
    console.log('Strict (valid):', validStrictResult.valid);
    

    which outputs:

    Relaxed (invalid): true
    Relaxed (valid): true
    Strict (invalid): false Unknown property (not in schema) /code
    Strict (valid): true
    

    The third argument to validateResult specifies whether to do recursive checking. It's not immediately clear, but I believe that the default is false (as provided in the example above).