You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用xUnit测试自定义JsonConverter时无法实例化JsonReader的解决方法

测试自定义JsonConverter的ReadJson方法:解决JsonReader无法实例化的问题

JsonReader是抽象类,不能直接实例化,你可以通过以下几种方式解决:

1. 使用JsonTextReader(Newtonsoft.Json的具体实现)

JsonTextReader是JsonReader的具体子类,可直接基于字符串或流实例化,适合直接测试ReadJson的核心逻辑:

using System.IO;
using Newtonsoft.Json;
using Xunit;

public class CustomConverterTests
{
    [Fact]
    public void ReadJson_WhenTypeIsOne_ReturnsOneEntity()
    {
        // 准备测试用的JSON字符串
        var testJson = "{\"type\":\"One\",\"content\":\"test content\"}";
        var stringReader = new StringReader(testJson);
        // 实例化具体的JsonReader实现
        var jsonReader = new JsonTextReader(stringReader);

        var converter = new YourCustomConverter();
        // 调用ReadJson方法,传入必要参数
        var result = converter.ReadJson(
            jsonReader, 
            typeof(BaseEntity), 
            existingValue: null, 
            serializer: JsonSerializer.CreateDefault()
        );

        // 断言结果类型正确
        Assert.IsType<One>(result);
        var oneEntity = result as One;
        Assert.Equal("test content", oneEntity.Content);
    }
}

2. 用Moq模拟JsonReader(适合复杂场景)

如果需要精准控制JsonReader的读取行为(比如模拟异常、特定的token序列),可以用Moq框架创建JsonReader的模拟对象:

首先安装Moq包:Install-Package Moq,然后编写测试:

using Moq;
using Newtonsoft.Json;
using Xunit;

public class CustomConverterTests
{
    [Fact]
    public void ReadJson_WhenTypeIsTwo_ReturnsTwoEntity()
    {
        var mockReader = new Mock<JsonReader>();

        // 模拟JSON对象的读取序列:StartObject → PropertyName → String → PropertyName → String → EndObject
        mockReader.SetupSequence(r => r.TokenType)
            .Returns(JsonToken.StartObject)
            .Returns(JsonToken.PropertyName)
            .Returns(JsonToken.String)
            .Returns(JsonToken.PropertyName)
            .Returns(JsonToken.String)
            .Returns(JsonToken.EndObject);

        // 模拟属性名和对应的值
        mockReader.SetupSequence(r => r.Value)
            .Returns("type")
            .Returns("Two")
            .Returns("data")
            .Returns("sample data");

        var converter = new YourCustomConverter();
        var result = converter.ReadJson(
            mockReader.Object, 
            typeof(BaseEntity), 
            null, 
            JsonSerializer.CreateDefault()
        );

        Assert.IsType<Two>(result);
        var twoEntity = result as Two;
        Assert.Equal("sample data", twoEntity.Data);
    }
}

3. 间接测试(通过JsonConvert.DeserializeObject)

如果不需要单独测试ReadJson方法,而是测试转换器的整体功能,直接用JsonConvert.DeserializeObject调用转换器,更贴近实际业务场景:

using Newtonsoft.Json;
using Xunit;

public class CustomConverterTests
{
    [Fact]
    public void DeserializeObject_WithValidJson_ReturnsCorrectEntity()
    {
        var testJson = "{\"type\":\"One\",\"content\":\"test\"}";
        var settings = new JsonSerializerSettings
        {
            Converters = new List<JsonConverter> { new YourCustomConverter() }
        };

        var result = JsonConvert.DeserializeObject<BaseEntity>(testJson, settings);

        Assert.IsType<One>(result);
    }
}

内容的提问来源于stack exchange,提问作者Alejandro Gomez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 07:03:28