How the Mock JsonReader module tests a custom JsonConverter

Wrote a custom JsonConverter to handle various Json formats that are returned by different versions of the same api. One application makes a request for several other applications, and we don’t know which format will be returned, so JsonConverter will handle this and seems to work well. I need to add unit tests to the project, except that I did not find useful resources to help expose some of the Newtonsoft.Json objects, mainly JsonReader.

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jsonValue = JObject.Load(reader);
        if(jsonValue == null)
        {
            return null;
        }

        var responseData = ReadJsonObject(jsonValue);
        return responseData;
    }

    [TestMethod]
    public void ReadJsonReturnNullForNullJson()
    {
        var converter = new DataConverter();

        _mockJsonReader.Setup(x => x.Value).Returns(null);

        var responseData = converter.ReadJson(_mockJsonReader.Object, typeof(ProbeResponseData), null, _mockJsonSerializer.Object);

        Assert.IsNull(responseData);
    }

ReadJson. JsonReader, json, , Json (JObject). unit test "Newtonsoft.JsonReaderException: JObject JsonReader. ". "

+6
5

DeserializeObject<T> ReadJson .

[TestMethod]
public void ReadJsonVerifyTypeReturned()
{
    var testJson = CreateJsonString();

    var result = JsonConvert.DeserializeObject<ProbeResponseData>(testJson);
    var resultCheck = result as ProbeResponseData;

    Assert.IsNotNull(resultCheck);
}
+4

, ?

public class JsonReaderThatReturnsNull : JsonReader
{
    public override bool Read()
    {
        return true;
    }

    public override object Value => null;
}
0

, . JsonConverterAttribute, , , :

var serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(new MyJsonConverter());

var serializer = JsonSerializer.Create(serializerSettings);

var jObject = JObject.Parse(myString);
var result = jObject.ToObject<MyObject>(serializer);
0

, .

DeserializedType result = JsonConvert.DeserializeObject<DeserializedType>(json, new Converter(parms));

0

JsonConvert JsonSerializer , , , . , , JSON.NET , , , , , - , JSON.NET , .

:

public readonly struct UserId
{
  public static readonly UserId Empty = new UserId();

  public UserId(int value)
  {
    Value = value;
    HasValue = true;
  }

  public int Value { get; }
  public bool HasValue { get; }
}

, int. number JSON intUserId. , :

public class MyStringConverter
{
  public override bool CanConvert(Type objectType) => objectType == typeof(UserId);

  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  {
    int? id = serializer.Deserialize<int?>(reader);
    if (!id.HasValue)
    {
      return UserId.Empty;
    }

    return new UserId(id.Value);
  }
}

WriteJson , .

:

[Fact]
public void UserIdJsonConverter_CanConvertFromJsonNumber()
{
    // Arrange
    var serialiser = new JsonSerializer();
    var reader = CreateJsonReader("10");
    var converter = new UserId.UserIdJsonConverter();

    // Act
    var result = converter.ReadJson(reader, typeof(UserId), null, serialiser);

    // Assert
    Assert.NotNull(result);
    Assert.IsType<UserId>(result);

    var id = (UserId)result;
    Assert.True(id.HasValue);
    Assert.Equal(10, id.Value);
}

private JsonTextReader CreateJsonReader(string json)
    => new JsonTextReader(new StringReader(json));

ReadJson , , . , JsonReader , JsonReader JsonSerializer , .

The problem with using JsonConvertor JsonSerializerto start the full deserialization process is that you introduce other logic that is largely outside your control. That is, if during deserialization, JSON.NET actually makes a different decision and your custom converter is never used, your test is not responsible for testing JSON.NET itself, but for what your custom converter actually does.

0
source

Source: https://habr.com/ru/post/1687829/


All Articles