簡體   English   中英

C#單元測試Newtonsoft JSON模型

[英]C# Unit testing a Newtonsoft JSON model

我從單元測試開始,而與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中沒有Null值或空字符串,因此具有null值的測試會使測試崩潰
  • 如果有人更改了JSON並刪除了屬性對象中的一個字段(例如city_name),則測試將失敗,所以我知道我需要調整模型或返回原始JSON格式
  • 檢查JSON值的格式,在這種情況下,它們都是字符串,可以插入模型中
  • 從較短版本的JSON文件運行注入,僅向模型中輸入3個條目,以確保一切正常

我在正確的道路上以及如何做到這一點,這將極大地幫助我啟動其他許多事情。

謝謝!

不需要進行單元測試,而是利用Newtonsoft的JSON驗證。

// 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
    };
  }
}

單元測試將針對Controller,以斷言它使用了驗證器來確保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);
}

該測試完成的工作是斷言我們的控制器將調用驗證邏輯來​​評估我們提供的JSON。 如果有人修改控制器並刪除對Validate的調用,則測試將失敗。

您不需要為這樣的測試編寫JSON對象,“ fred”就可以了,因為它只是模擬可以識別的占位符。 在這種情況下,模擬程序配置為:“我希望使用特定的值來調用。[fred]”“獲得該值時,我會說它無效,並且將包含一組特定的驗證錯誤。” 從那里,您可以斷言Controller的結果響應,以查看它是否反映了驗證錯誤。 我們還要求最后的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....
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM