使用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
相关产品推荐
相关产品推荐

