Разрешить JSON $ ref в модульных тестах с помощью NJsonSchema - PullRequest
0 голосов
/ 04 июня 2018

Я разбил свою схему JSON на несколько файлов и ссылаюсь на них, как требуется, стандартным способом ("$ref": http://rootpath/otherfile.json#/definitions/link).

Файлы JSON являются встроенными ресурсами в проекте.Значение rootpath изменяется в зависимости от того, где оно развернуто.Но в производстве все работает нормально (делается запрос, ответ JSON получается так же, как схема, при проверке ответа по схеме NJsonSchema внутренне получает эталонную схему (схемы) и извлекает то, что требуется для завершения проверки)

Однако, когда дело доходит до тестирования, это другой вопрос.Ответ в порядке, и получить первую схему заглушки.rootpath таков, что все относительно http://testapi/, но на самом деле этого не существует.Поэтому, когда NJsonSchema пытается получить эталонную схему, она выглядит примерно как http://testapi/otherfile.json#/definitions/link, что явно не получается.

После чтения this Я думаю, что я хочу использовать перегрузку для полученияJsonSchema4 объект, который позволяет мне указать JsonReferenceResolver, тогда я мог бы использовать значение по умолчанию в производственном процессе и внедрить свой собственный для тестирования так, чтобы он искал где-то $ref, который я контролирую и будет существовать.Но я не вижу никакой документации или примеров по этому вопросу.

Примеры схем:

{ // root.json
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "@Model.Root/schemas/root.json",
    "title": "Root",
    "properties": {
        "link": { "$ref": "@Model.Root/schemas/common.json#/definitions/link" }             
    },
    "required": [ "link" ]
}

{ // common.json - different file to the above
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "@Model.Root/schemas/common.json",
    "definitions": {
        "link": {
            "title": "Link",
            "type": "object",
            "properties": {
                "rel": { "type": "string" },
                "href": { "type": "string" }
            },
            "required": [ "rel", "href" ]
        }
    }
}

Пример ответа:

{
    "schema": "http://testapi/schemas/root.json",
    "link": { "rel": "self", "href": "http://testapi/root" }
};

Код проверки (C #):

using NJsonSchema;
using NJsonSchema.Validation;
...
JsonSchema4 schema = await JsonSchema4.FromJsonAsync(<contents of root.json file>);
string response = "{ ""link"": { ""rel"": ""self"", ""href"": ""http://testapi/root"" } }";
ICollection<ValidationError> errors = schema.Validate(response);
...

1 Ответ

0 голосов
/ 13 июня 2018

Мои предположения об указании JsonReferenceResolver были в правой строке.В приведенном выше примере я не смог получить ссылку на common.json из root.json для «работы» в тестовой среде, потому что в этой среде сервис / путь не существовал.

Так что при настройкеЯ знаю, что такое common.json, то есть знаю, что это содержимое в виде строки, и поэтому могу получить его в виде схемы (JsonSchema4 commonSchema = JsonSchema4.FromJsonAsync(commonJsonAsString).Result;).

Используя это, я могу установить 'Factory Resolver Factory''и добавьте в него ссылку на документ так, чтобы все ссылки на http://testapi/schemas/common.json#/... были получены из моего commonSchema, т. е.

private Func<JsonSchema4, JsonReferenceResolver> referenceResolverFactory;
this.referenceResolverFactory = x =>
{
    JsonSchemaResolver schemaResolver = new JsonSchemaResolver(x, new JsonSchemaGeneratorSettings());
    JsonReferenceResolver referenceResolver = new JsonReferenceResolver(schemaResolver);
    referenceResolver.AddDocumentReference("http://testapi/schemas/common.json", commonSchema);

    return referenceResolver;
};

Различные ссылки могут быть разрешены путем добавления большего количества ссылок на документы таким же образом.

Затем, когда я пытаюсь преобразовать схему root.json (со ссылкой на common.json) или другую схему (которая ссылается на common.json), я использую перегрузку FromJsonAsync, которая передается в referenceResolverFactory:

private bool GetAndValidateResponse(string schemaName, string response, string schemaAsString)
{
    // schemaName:     Name of the schema being validated, e.g. "root.json"
    // response:       http response body as a string, see 'Example response' in question
    // schemaAsString: The schema being validate as a string, e.g. root.json contents in question
    //
    // Check the response object against the schema
    JsonSchema4 schema = JsonSchema4.FromJsonAsync(schemaAsString, schemaName, this.referenceResolverFactory).Result;
    ICollection<ValidationError> errors = schema.Validate(response);

    return errors.Count < 1;
}

В моем случае для модульных тестов меня интересовало только то, что он действителен или нет, поэтому логическое возвращаемое значение.Если вас интересуют точные ошибки, очевидно, вы можете вернуть коллекцию.

Также я настраиваю фабрику только один раз для класса юнит-теста, а не для теста.Тем не менее, он по праву идет на завод для каждого ref в схеме.

...