public async Task BuffersRequestBody_UsingDefaultOptions() { // Arrange var content = "{name: 'Person Name', Age: '30'}"; var logger = GetLogger(); var formatter = new JsonInputFormatter( logger, _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider, new MvcOptions()); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = new DefaultHttpContext(); httpContext.Features.Set <IHttpResponseFeature>(new TestResponseFeature()); httpContext.Request.Body = new NonSeekableReadStream(contentBytes); httpContext.Request.ContentType = "application/json"; var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); var userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); Assert.True(httpContext.Request.Body.CanSeek); httpContext.Request.Body.Seek(0L, SeekOrigin.Begin); result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); }
public async Task JsonFormatterReadsComplexTypes() { // Arrange var content = "{name: 'Person Name', Age: '30'}"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: new ModelStateDictionary(), metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); var userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); }
public async Task ReadAsync_WhenSuppressJsonDeserializationExceptionMessagesIsTrue_DoesNotWrapJsonInputExceptions() { // Arrange var logger = GetLogger(); var formatter = new JsonInputFormatter( logger, _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider, suppressInputFormatterBuffering: false, suppressJsonDeserializationExceptionMessages: true); var contentBytes = Encoding.UTF8.GetBytes("{"); var modelStateKey = string.Empty; var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.True(result.HasError); Assert.True(!modelState.IsValid); Assert.True(modelState.ContainsKey(modelStateKey)); var modelError = modelState[modelStateKey].Errors.Single(); Assert.IsNotType <InputFormatterException>(modelError.Exception); Assert.Empty(modelError.ErrorMessage); }
public async Task ReadAsync_WithInputThatDeserializesToNull_SetsModelOnlyIfAllowingEmptyInput(string content, bool allowEmptyInput, bool expectedIsModelSet) { // Arrange var logger = GetLogger(); var formatter = new JsonInputFormatter(logger, _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(object)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader, treatEmptyInputAsDefaultValue: allowEmptyInput); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); Assert.Equal(expectedIsModelSet, result.IsModelSet); Assert.Null(result.Model); }
public async Task ReadAsync_ReadsValidArray_AsList(Type requestedType) { // Arrange var content = "[0, 23, 300]"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger, _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(requestedType); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); var integers = Assert.IsType <List <int> >(result.Model); Assert.Equal(new int[] { 0, 23, 300 }, integers); }
public async Task JsonFormatterReadsSimpleTypes(string content, Type type, object expected) { // Arrange var logger = GetLogger(); var formatter = new JsonInputFormatter(logger, _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider); var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(type); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: new ModelStateDictionary(), metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); Assert.Equal(expected, result.Model); }
public async Task ReadAsync_AddsModelValidationErrorsToModelState() { // Arrange var content = "{name: 'Person Name', Age: 'not-an-age'}"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.True(result.HasError); Assert.Equal( "Could not convert string to decimal: not-an-age. Path 'Age', line 1, position 39.", modelState["Age"].Errors[0].Exception.Message); }
public async Task ReadAsync_InvalidArray_AddsOverflowErrorsToModelState() { // Arrange var content = "[0, 23, 300]"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(byte[])); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.True(result.HasError); Assert.Equal("The supplied value is invalid for Byte.", modelState["[2]"].Errors[0].ErrorMessage); Assert.Null(modelState["[2]"].Errors[0].Exception); }
public async Task ReadAsync_InvalidComplexArray_AddsOverflowErrorsToModelState() { // Arrange var content = "[{name: 'Name One', Age: 30}, {name: 'Name Two', Small: 300}]"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User[])); var context = new InputFormatterContext( httpContext, modelName: "names", modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.True(result.HasError); Assert.Equal( "Error converting value 300 to type 'System.Byte'. Path '[1].Small', line 1, position 59.", modelState["names[1].Small"].Errors[0].Exception.Message); }
public async Task ReadAsync_UsesTryAddModelValidationErrorsToModelState() { // Arrange var content = "{name: 'Person Name', Age: 'not-an-age'}"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); modelState.MaxAllowedErrors = 3; modelState.AddModelError("key1", "error1"); modelState.AddModelError("key2", "error2"); // Act var result = await formatter.ReadAsync(context); // Assert Assert.True(result.HasError); Assert.False(modelState.ContainsKey("age")); var error = Assert.Single(modelState[""].Errors); Assert.IsType <TooManyModelErrorsException>(error.Exception); }
public async Task ChangesTo_DefaultSerializerSettings_TakesEffect() { // Arrange // missing password property here var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}"); var logger = GetLogger(); var jsonFormatter = new JsonInputFormatter(logger); // by default we ignore missing members, so here explicitly changing it jsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error; var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8"); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(UserLogin)); var inputFormatterContext = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await jsonFormatter.ReadAsync(inputFormatterContext); // Assert Assert.True(result.HasError); Assert.False(modelState.IsValid); var modelErrorMessage = modelState.Values.First().Errors[0].Exception.Message; Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage); }
public async Task ReadAsync_AllowInputFormatterExceptionMessages_DoesNotWrapJsonInputExceptions() { // Arrange var formatter = new JsonInputFormatter( GetLogger(), _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider, new MvcOptions(), new MvcJsonOptions() { AllowInputFormatterExceptionMessages = true, }); var contentBytes = Encoding.UTF8.GetBytes("{"); var httpContext = GetHttpContext(contentBytes); var formatterContext = CreateInputFormatterContext(typeof(User), httpContext); // Act var result = await formatter.ReadAsync(formatterContext); // Assert Assert.True(result.HasError); Assert.True(!formatterContext.ModelState.IsValid); Assert.True(formatterContext.ModelState.ContainsKey(string.Empty)); var modelError = formatterContext.ModelState[string.Empty].Errors.Single(); Assert.Null(modelError.Exception); Assert.NotEmpty(modelError.ErrorMessage); }
public override Task <InputFormatterResult> ReadAsync(InputFormatterContext context) { using (new ProfileContext("input_formatter - Json Input Formatter - ReadAsync")) { return(_inner.ReadAsync(context)); } }
public async Task ReadAsync_RegistersJsonInputExceptionsAsInputFormatterException( string content, string modelStateKey, string expectedMessage) { // Arrange var logger = GetLogger(); var formatter = new JsonInputFormatter(logger, _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.True(result.HasError); Assert.True(!modelState.IsValid); Assert.True(modelState.ContainsKey(modelStateKey)); var modelError = modelState[modelStateKey].Errors.Single(); Assert.Equal(expectedMessage, modelError.ErrorMessage); }
public async Task SuppressInputFormatterBufferingSetToTrue_UsingMutatedOptions() { // Arrange var content = "{name: 'Person Name', Age: '30'}"; var logger = GetLogger(); var mvcOptions = new MvcOptions(); mvcOptions.SuppressInputFormatterBuffering = false; var formatter = new JsonInputFormatter(logger, _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider, mvcOptions); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = new DefaultHttpContext(); httpContext.Features.Set <IHttpResponseFeature>(new TestResponseFeature()); httpContext.Request.Body = new NonSeekableReadStream(contentBytes); httpContext.Request.ContentType = "application/json"; var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act // Mutate options after passing into the constructor to make sure that the value type is not store in the constructor mvcOptions.SuppressInputFormatterBuffering = true; var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); var userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); Assert.False(httpContext.Request.Body.CanSeek); result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); Assert.Null(result.Model); }
public async Task Version_2_1_Constructor_SuppressInputFormatterBufferingSetToTrue_UsingMutatedOptions() { // Arrange var mvcOptions = new MvcOptions() { SuppressInputFormatterBuffering = false, }; var formatter = new JsonInputFormatter( GetLogger(), _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider, mvcOptions, new MvcJsonOptions()); var content = "{name: 'Person Name', Age: '30'}"; var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = new DefaultHttpContext(); httpContext.Features.Set <IHttpResponseFeature>(new TestResponseFeature()); httpContext.Request.Body = new NonSeekableReadStream(contentBytes); httpContext.Request.ContentType = "application/json"; var formatterContext = CreateInputFormatterContext(typeof(User), httpContext); // Act // Mutate options after passing into the constructor to make sure that the value type is not store in the constructor mvcOptions.SuppressInputFormatterBuffering = true; var result = await formatter.ReadAsync(formatterContext); // Assert Assert.False(result.HasError); var userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); Assert.False(httpContext.Request.Body.CanSeek); result = await formatter.ReadAsync(formatterContext); // Assert Assert.False(result.HasError); Assert.Null(result.Model); }
public async Task Version_2_1_Constructor_BuffersRequestBody_UsingDefaultOptions() { // Arrange var formatter = new JsonInputFormatter( GetLogger(), _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider, new MvcOptions(), new MvcJsonOptions()); var content = "{name: 'Person Name', Age: '30'}"; var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = new DefaultHttpContext(); httpContext.Features.Set <IHttpResponseFeature>(new TestResponseFeature()); httpContext.Request.Body = new NonSeekableReadStream(contentBytes); httpContext.Request.ContentType = "application/json"; var formatterContext = CreateInputFormatterContext(typeof(User), httpContext); // Act var result = await formatter.ReadAsync(formatterContext); // Assert Assert.False(result.HasError); var userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); Assert.True(httpContext.Request.Body.CanSeek); httpContext.Request.Body.Seek(0L, SeekOrigin.Begin); result = await formatter.ReadAsync(formatterContext); // Assert Assert.False(result.HasError); userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); }
public async Task SuppressInputFormatterBufferingSetToTrue_DoesNotBufferRequestBody() { // Arrange var content = "{name: 'Person Name', Age: '30'}"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger, _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider, suppressInputFormatterBuffering: true); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = new DefaultHttpContext(); httpContext.Features.Set <IHttpResponseFeature>(new TestResponseFeature()); httpContext.Request.Body = new NonSeekableReadStream(contentBytes); httpContext.Request.ContentType = "application/json"; var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); var userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); // Reading again should not fail as the request body should have been buffered by the formatter result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); Assert.Null(result.Model); }
public async Task Version_2_0_Constructor_SuppressInputFormatterBufferingSetToTrue_DoesNotBufferRequestBody() { // Arrange #pragma warning disable CS0618 var formatter = new JsonInputFormatter( GetLogger(), _serializerSettings, ArrayPool <char> .Shared, _objectPoolProvider, suppressInputFormatterBuffering: true); #pragma warning restore CS0618 var content = "{name: 'Person Name', Age: '30'}"; var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = new DefaultHttpContext(); httpContext.Features.Set <IHttpResponseFeature>(new TestResponseFeature()); httpContext.Request.Body = new NonSeekableReadStream(contentBytes); httpContext.Request.ContentType = "application/json"; var formatterContext = CreateInputFormatterContext(typeof(User), httpContext); // Act var result = await formatter.ReadAsync(formatterContext); // Assert Assert.False(result.HasError); var userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); Assert.False(httpContext.Request.Body.CanSeek); result = await formatter.ReadAsync(formatterContext); // Assert Assert.False(result.HasError); Assert.Null(result.Model); }
public async Task ReadAsync_ReadsValidArray_AsList(Type requestedType) { // Arrange var content = "[0, 23, 300]"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger, _serializerSettings, ArrayPool<char>.Shared, _objectPoolProvider); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(requestedType); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); var integers = Assert.IsType<List<int>>(result.Model); Assert.Equal(new int[] { 0, 23, 300 }, integers); }
public async Task JsonFormatterReadsComplexTypes() { // Arrange var content = "{name: 'Person Name', Age: '30'}"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: new ModelStateDictionary(), metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); var userModel = Assert.IsType<User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); }
public async Task ReadAsync_UsesTryAddModelValidationErrorsToModelState() { // Arrange var content = "{name: 'Person Name', Age: 'not-an-age'}"; var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(User)); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); modelState.MaxAllowedErrors = 3; modelState.AddModelError("key1", "error1"); modelState.AddModelError("key2", "error2"); // Act var result = await formatter.ReadAsync(context); // Assert Assert.True(result.HasError); Assert.False(modelState.ContainsKey("age")); var error = Assert.Single(modelState[""].Errors); Assert.IsType<TooManyModelErrorsException>(error.Exception); }
public async Task CustomSerializerSettingsObject_TakesEffect() { // Arrange // missing password property here var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}"); var logger = GetLogger(); var jsonFormatter = new JsonInputFormatter(logger); // by default we ignore missing members, so here explicitly changing it jsonFormatter.SerializerSettings = new JsonSerializerSettings() { MissingMemberHandling = MissingMemberHandling.Error }; var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8"); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(UserLogin)); var inputFormatterContext = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await jsonFormatter.ReadAsync(inputFormatterContext); // Assert Assert.True(result.HasError); Assert.False(modelState.IsValid); var modelErrorMessage = modelState.Values.First().Errors[0].Exception.Message; Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage); }
public async Task JsonFormatterReadsSimpleTypes(string content, Type type, object expected) { // Arrange var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(type); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: new ModelStateDictionary(), metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); Assert.Equal(expected, result.Model); }