C # Unit-тестирование модели Newtonsoft JSON - PullRequest
0 голосов
/ 20 сентября 2018

Я начинаю с модульного тестирования и делаю это с XUnit.

У меня есть модель:

using Newtonsoft.Json;
namespace HomeAddressSearch
{
    public class Properties
    {
        [Required]
        [JsonProperty(PropertyName = "civic_number")]
        public string CivicNumber { get; set; }

        [JsonProperty(PropertyName = "address")]
        public string Address { get; set; }

        [JsonProperty(PropertyName = "postal_code")]
        public string PostalCode { get; set; }

        [JsonProperty(PropertyName = "city_name")]
        public string CityName { get; set; }
    }
}

, и у меня есть JSON, из которого я получаю такие значения, как:

[
  {
    "properties": {
      "civic_number": "100",
      "address": "100, king street",
      "postal_code": "H0H0H0",
      "city_name": "Windsor"
    },
    "owner": {
      "name": "John Doe",
      "age": "40"
    },
  }
]

Итак, я хочу протестировать эту модель, и поэтому я хочу:

  • Поскольку CivicNumber является обязательным, я хочу убедиться, что в нуле нет пустого значения или пустой строки.JSON, то есть тест с нулевым значением, приводящий к сбою теста
  • Если кто-нибудь изменит JSON и удалит одно из полей в объекте свойств, например city_name, тогда тест не пройден, поэтому я знаю, что мне тоже нужночтобы адаптировать мою модель или вернуться к исходному формату JSON
  • Проверьте, что формат значений JSON, в этом случае все они строковые, можно использовать в моей модели
  • Запуститеинъекция из более короткой версии файла JSON с только 3 записями в модель, чтобы убедиться, что все в порядке

Я на правильном пути и как это сделать, что очень помогло бы и кикстартя многодругих вещей.

Спасибо!

1 Ответ

0 голосов
/ 20 сентября 2018

Это не то, что вам нужно для модульного тестирования, а скорее использование JSON-проверки Newtonsoft.

// Generate a JSON schema from your object.
var schemaGenerator = new JSchemaGenerator();
var schema = schemaGenerator.Generate(typeof(HomeAddressSearch.Properties)); 

// Parse the JSON passed in, then validate it against the schema before proceeding.
List<ValidationErrors> validationErrors;
JObject addressToValidate = JObject.Parse(jsonStringToValidate);
bool isValid = addressToValidate.IsValid(schema, out validationErrors);

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

Модульные тесты подходят для утверждения статического поведения кода, поэтому, если ваша схема JSON задает правила, утверждение, которое выполняет модульный тест:

  • Утверждает, что ваш код проверял JSONСхема и отклонил ее, если она недействительна.
  • Любое поведение, которое ваш код должен делать с допустимыми сценариями данных JSON.

** Редактировать ** Чтобы уточнить использование валидации, затем выполните модульное тестирование, котороепроверка выполняется:

Допустим, у нас есть API, который принимает данные JSON в виде строки, а не класса: (где мы должны иметь возможность использовать model.IsValid ())

public class AddressController : ApiController
{
  private readonly IJsonEntityValidator<HomeAddressSearch.Properties> _validator = null;

  public AddressController(IJsonEntityValidator validator)
  {
    _validator = validator;
  }
  public ActionResult Search(string jsonModel)
  { 
    if(string.IsNullOrEmpty(jsonModel))
      // handle response for missing model.

    var result = _validator.Validate<HomeAddressSearch.Properties>(jsonModel);
    if (!result.IsValid) 
      // handle validation failure for the model.
  }
}

public class JSonEntityValidator<T> : IJsonEntityValidator<T> where T: class
{
  IJsonEntityValidator<T>.Validate(string jsonModel)
  {
    // Generate a JSON schema from your object.
    var schemaGenerator = new JSchemaGenerator();
    var schema = schemaGenerator.Generate(typeof(T)); 

    // Parse the JSON passed in, then validate it against the schema before proceeding.
    List<ValidationErrors> validationErrors;
    JObject model = JObject.Parse(jsonModel);
    bool isValid = model.IsValid(schema, out validationErrors);
    return new JsonValidateResult
    {
      IsValid = isValid,
      ValidationErrors = validationErrors
    };
  }
}

Модульный тест был бы против Контроллера, чтобы утверждать, что он использовал валидатор, чтобы гарантировать, что данные JSON были действительны:

[Test]
public void EnsureHomeAddressSearchValidatesProvidedJson_InvalidJSONScenario()
{
  string testJson = buildInvalidJson(); // the value here doesn't matter beyond being recognized by our mock as being passed to the validation.
  var mockValidator = new Mock<IJsonEntityValidator<HomeAddressSearch.Properties>>();
  mockValidator.Setup(x => x.Validate(testJson)
    .Returns(new JsonValidationResult { IsValid = false, ValidationErrors = new ValidationError[] { /* populate a set of validation errors. */ }.ToList()});
  var testController = new AddressController(mockValidator.Object);
  var result = testController.Search(testJson);
  // Can assess the result from the controller based on the scenario validation errors returned....

  // Validate that our controller called the validator.
  mockValidator.Verify(x => x.Validate(testJson), Times.Once);
}

Что этот тест приmplishes утверждает, что наш контроллер будет вызывать логику проверки для оценки предоставленного нами JSON.Если кто-то изменяет контроллер и удаляет вызов Validate, тест не пройден.

Вам не нужно составлять JSON-объект для теста, подобного этому, "fred" будет в порядке, так как это просто заполнитель для распознавания макета.Макет в этом сценарии настроен так: «Я ожидаю вызова с определенным значением. [Fred]» «Когда я получу это значение, я скажу, что оно недействительно, и я собираюсь включитьконкретный набор ошибок валидации. "Оттуда вы можете утверждать ответ результата от Контроллера, чтобы видеть, отражает ли он ошибки проверки.Мы также просим Mock в конце убедиться, что он был вызван с определенным значением.

Теперь, если вы также хотите принудительно применить / утвердить изменения вашей схемы, вы можете написать тесты для самого вашего валидатора.Например, для обнаружения кого-либо, удаляющего или изменяющего атрибут в вашей модели.

[Test]
EnsureHomeAddressValidatorExpectsCivicNumberIsRequired()
{
  var testJson = generateJsonMissingCivicNumber();
  IJsonEntityValidator<HomeAddressSearch.Properties> testValidator = new JsonEntityValidator<HomeAddressSearch.Properties>();
  var result = testValidator.Validate(testJson);
  Assert.IsFalse(result.IsValid);
  // Assert result.ValidationErrors....
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...