All Projects → fesor → json_matcher

fesor / json_matcher

Licence: other
Library for simplifying data verification in functional tests for your JSON-based APIs

Programming Languages

PHP
23972 projects - #3 most used programming language

Projects that are alternatives of or similar to json matcher

beJS
Simple, light-weight assertions framework for javascript
Stars: ✭ 12 (-50%)
Mutual labels:  assertions, assertion-library
jsonassert
A Go test assertion library for verifying that two representations of JSON are semantically equal
Stars: ✭ 102 (+325%)
Mutual labels:  assertions, assertion-library
Enzyme
JavaScript Testing utilities for React
Stars: ✭ 19,781 (+82320.83%)
Mutual labels:  assertions, assertion-library
fluentcheck
Fluent assertions for Python
Stars: ✭ 79 (+229.17%)
Mutual labels:  assertions, assertion-library
robotframework-jsonvalidator
Robot Framework library for JSON validation
Stars: ✭ 21 (-12.5%)
Mutual labels:  json-schema, jsonpath
Verify Json
verify-json
Stars: ✭ 208 (+766.67%)
Mutual labels:  json-schema
Json Schema Tools
Packages for working with JSON Schema and JSON Hyper-Schema
Stars: ✭ 232 (+866.67%)
Mutual labels:  json-schema
Api Development Tools
📚 A collection of useful resources for building RESTful HTTP+JSON APIs.
Stars: ✭ 2,519 (+10395.83%)
Mutual labels:  json-schema
Json schemer
JSON Schema validator. Supports drafts 4, 6, and 7.
Stars: ✭ 199 (+729.17%)
Mutual labels:  json-schema
json-kotlin-schema-codegen
Code generation for JSON Schema (Draft 07)
Stars: ✭ 52 (+116.67%)
Mutual labels:  json-schema
Vue Form Json Schema
Create forms using JSON schema. Bring your components!
Stars: ✭ 253 (+954.17%)
Mutual labels:  json-schema
Jsonon
A json online view
Stars: ✭ 228 (+850%)
Mutual labels:  json-schema
Vue Json Edit
Visual JSON editor built as an vue component. Provides a basic GUI
Stars: ✭ 207 (+762.5%)
Mutual labels:  json-schema
Kubernetes Json Schema
A set of JSON schemas for various Kubernetes versions, extracted from the OpenAPI definitions
Stars: ✭ 234 (+875%)
Mutual labels:  json-schema
Validr
A simple, fast, extensible python library for data validation.
Stars: ✭ 205 (+754.17%)
Mutual labels:  json-schema
Rxdb
🔄 A client side, offline-first, reactive database for JavaScript Applications
Stars: ✭ 16,670 (+69358.33%)
Mutual labels:  json-schema
React Json Editor
A dynamic form component for react using JSON-Schema.
Stars: ✭ 201 (+737.5%)
Mutual labels:  json-schema
Activerecord json validator
🔩 ActiveRecord::JSONValidator makes it easy to validate JSON attributes against a JSON schema.
Stars: ✭ 220 (+816.67%)
Mutual labels:  json-schema
Full Stack Fastapi Couchbase
Full stack, modern web application generator. Using FastAPI, Couchbase as database, Docker, automatic HTTPS and more.
Stars: ✭ 243 (+912.5%)
Mutual labels:  json-schema
Angular Schema Form
Generate forms from a JSON schema, with AngularJS!
Stars: ✭ 2,456 (+10133.33%)
Mutual labels:  json-schema

Json Matcher

Build Status Latest Stable Version Latest Unstable Version License Scrutinizer Code Quality Total Downloads

Assertion library for simplifying JSON data and structure verification in your tests. It's framework-agnostic, so you can use it with PhpUnit, PhpSpec, Peridot or whatever framework you use.

Why another JSON assertion library?

If you tried to test your JSON based REST APIs, then you probably faced a several issues:

  • You can't simply check is a response is equal to given string as there are things like server-generated IDs and timestamps.
  • Key ordering should be the same both for your API and for expected JSON.
  • Matching the whole responses breaks DRY for the tests

All these issues can be solved with two simple things: JSON normalization and key exclusion on matching. This is what this library does. It provides you a way to verify data in given JSON in multiple steps instead of one big assertion.

For example we are developing an friend list feature for our API for. What we want to check is only is given user presents in response, we don't want to check whole response, it could be done via json schema validation or on another test cases.

$alice = new User('Alice', 'Miller');
$john = new User('John', 'Smith');
$alice->addFriend($john);

$json = JsonMatcher::create(
    json_encode($alice->toArrayIncludingFriends()), ['id', 'created_at']
);

In above example we just created an JsonMatcher instance and specified excluded-by-default keys (id and created_at). Excluded keys will be removed from JSON and it's values will not interfere in equality assertion. You can also override this list of keys via matching excluding and including options.

Then we can check is John presents in Alice's friend list at some specific position via json paths:

$json->equal(json_encode($john->toArray()), ['at' => 'friends/0']);

Or if we don't know specific position, we can just check is John just presents in our friendlist.

$json->includes(json_encode($john->toArray()), ['at' => 'friends']);

Or we can just verify is any John presents in Alice's friend list:

$json->includes('{"first_name": "John"}'), ['at' => 'friends']);

Getting started

You can install this library via composer:

composer require fesor/json_matcher

Then you will need an JsonMatcher instance to be created. To do this, you can:

  • manually create instance with all dependencies and set subject
  • use named constructor JsonMatcher::create as static factory-method. It will handle all dependencies for you.
  • use JsonMatcherFactory. This is useful when you have some IoC container in your test framework (Behat for example). In this case you'll need to register this class as a service.

Subject on which assertion will be preformed is setted up in matcher consturctor. If you want to reuse the same instance of matcher for every assertions, you can just change subject via setSubject method.

Example:

$jsonResponse = JsonMatcher::create($response->getContent());

// or you can use factory instead
$jsonResponse = $matcherFactory->create($response->getContent());

// and there you go, for example you may use something like this 
// for your gherkin steps implementations
$jsonResponse
    ->hasSize(1, ['at' => 'friends']) // checks that list of friends was incremented
    ->includes($friend, ['at' => 'friends']) // checks that correct record contained in collection
;

You can provide list of excluded-by-default keys as second argument in constructors:

$matcher = JsonMatcher::create($subject, ['id', 'created_at']);

Please note, that id key will be ignored by default.

Matchers

All matchers are supports fluent interface, negative matching and some options. See detailed description for more information about what options each matcher has.

equal

This is most commonly used matcher. You take two json strings and compare them. Except that before compassion this matcher will normalize structure of both JSON strings, reorder keys, exclude some of them (this is configurable) and then will simply assert that both strings are equal. You can specify list of excluded keys with excluding options:

$actualJson = '["id": 1, "json": "spec"]';
$expectedJson = '["json": "spec"]';
$matcher
    ->setSubject($actualJson)
    ->equal($expectedJson, ['excluding' => ['id']])
;

If you have some keys, which contains some time dependent value of some server-generated IDs it is more convenient to specify list of excluded-by-default keys when you construct matcher object:

$matcher = JsonMatcher::create($subject, ['id', 'created_at', 'updated_at']);

If you want the values for these keys to be taken into account during the matching, you can specify list of included keys with including options

$matcher = JsonMatcher::create($response->getContent(), ['id', 'created_at', 'updated_at']);
$jsonResponseSubject->equal($expectedJson, ['including' => ['id']]);

Also you can specify json path on which matching should be done via at options. We will back to this later since all matchers supports this option.

includes

This matcher works a little different from equal matcher. What it does is recursively scan subject JSON and tries to find any inclusions of JSON subset. This is useful for cases when you checking that some record exists in collection and you do not know or don't want to know specific path to it.

$json = <<<JSON
{
    "id": 1,
    "name": "Foo",
    "collection": [
        {"id": 1, "name": "Foo"},
        {"id": 2, "name": "Bar"},
    ]
}
JSON;

$matcher
    ->setSubject($json)
    // check for value inclusion
    ->includes('"Foo"')
    // checks is json subset presents in any item of collection
    ->includes('{"name": "Bar"}', ['at' => 'collection'])
    // checks is json presents in collection
    ->includes('{"name": "Bar", "value": "FooBar"}', ['at' => 'collection'])
;

Since this matcher works the same way as equal matcher, it accepts same options.

hasPath

This matcher checks if given JSON have specific path ot not.

$json = <<<JSON
{
    "collection": [
        "json",
        "matcher"
    ]
}
JSON;

$matcher
    ->setSubject($json)
    ->hasPath('collection/1')
;

hasSize

This matcher checks is collection in given JSON contains specific amount of entities.

$json = <<<JSON
{
    "collection": [
        "json",
        "matcher"
    ]
}
JSON;

$matcher
    ->setSubject($json)
    ->hasSize(2, ['at' => 'collection'])
;

hasType

$json = <<<JSON
{
    "collection": [
        {},
        "json",
        42,
        13.45
    ]
}
JSON;

$matcher
    ->setSubject($json)
    ->hasType('array', ['at' => 'collection'])
    ->hasType('object', ['at' => 'collection/0'])
    ->hasType('string', ['at' => 'collection/1'])
    ->hasType('integer', ['at' => 'collection/2'])
    ->hasType('float', ['at' => 'collection/3'])
;

Negative matching

To invert expectations just call matcher methods with not prefix:

$matcher
    ->setSubject($json)
    ->notEqual($expected)
    ->notIncludes($part)
;

Json Path

Also all methods have option, which specifies path which should be performed matching. For example:

$actual = <<<JSON
{
    "collection": [
        "item"
    ]
}
JSON;
$expected = '"item"';
JsonMatcher::create($actual)
    ->equal($expected, ['at' => 'collection/0'])
;

Contribution

Please welcome to contribute!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].