Restructure tests

This commit is contained in:
Ryan Brandenburg 2019-06-19 15:08:47 -07:00
parent aeaa0376d1
commit 8f99ca3fad
4 changed files with 106 additions and 45 deletions

View File

@ -78,23 +78,11 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
catch (JsonException jsonException) catch (JsonException jsonException)
{ {
var path = jsonException.Path; var path = jsonException.Path;
if (path.StartsWith("$.", StringComparison.Ordinal))
{
path = path.Substring(2);
}
if (path.StartsWith("$[", StringComparison.Ordinal))
{
path = path.Substring(1);
}
// Handle path combinations such as ""+"Property", "Parent"+"Property", or "Parent"+"[12]".
var key = ModelNames.CreatePropertyModelName(context.ModelName, path);
var formatterException = new InputFormatterException(jsonException.Message, jsonException); var formatterException = new InputFormatterException(jsonException.Message, jsonException);
var metadata = ModelNames.GetPathMetadata(context.Metadata, path); var metadata = ModelNames.GetPathMetadata(context.Metadata, path);
context.ModelState.TryAddModelError(key, formatterException, metadata); context.ModelState.TryAddModelError(path, formatterException, metadata);
Log.JsonInputException(_logger, jsonException); Log.JsonInputException(_logger, jsonException);

View File

@ -19,14 +19,6 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{ {
public abstract class JsonInputFormatterTestBase : LoggedTest public abstract class JsonInputFormatterTestBase : LoggedTest
{ {
internal enum Formatter
{
Newtonsoft,
SystemText
}
internal abstract Formatter CurrentFormatter { get; }
[Theory] [Theory]
[InlineData("application/json", true)] [InlineData("application/json", true)]
[InlineData("application/*", false)] [InlineData("application/*", false)]
@ -116,8 +108,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
} }
[Fact] [Fact]
public async Task JsonFormatter_EscapedKeys_Bracket() public virtual async Task JsonFormatter_EscapedKeys_Bracket()
{ {
var expectedKey = JsonFormatter_EscapedKeys_Bracket_Expected;
// Arrange // Arrange
var content = "[{\"It[s a key\":1234556}]"; var content = "[{\"It[s a key\":1234556}]";
var formatter = GetInputFormatter(); var formatter = GetInputFormatter();
@ -136,13 +130,15 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
formatterContext.ModelState.OrderBy(k => k.Key), formatterContext.ModelState.OrderBy(k => k.Key),
kvp => kvp =>
{ {
Assert.Equal("[0][\'It[s a key\']", kvp.Key); Assert.Equal(expectedKey, kvp.Key);
}); });
} }
[Fact] [Fact]
public async Task JsonFormatter_EscapedKeys() public virtual async Task JsonFormatter_EscapedKeys()
{ {
var expectedKey = JsonFormatter_EscapedKeys_Expected;
// Arrange // Arrange
var content = "[{\"It\\\"s a key\": 1234556}]"; var content = "[{\"It\\\"s a key\": 1234556}]";
var formatter = GetInputFormatter(); var formatter = GetInputFormatter();
@ -162,17 +158,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
formatterContext.ModelState.OrderBy(k => k.Key), formatterContext.ModelState.OrderBy(k => k.Key),
kvp => kvp =>
{ {
switch(CurrentFormatter) Assert.Equal(expectedKey, kvp.Key);
{
case Formatter.Newtonsoft:
Assert.Equal("[0]['It\"s a key']", kvp.Key);
break;
case Formatter.SystemText:
Assert.Equal("[0][\'It\\u0022s a key\']", kvp.Key);
break;
default:
throw new NotImplementedException();
}
}); });
} }
@ -285,12 +271,19 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
var formatterContext = CreateInputFormatterContext(typeof(List<ComplexModel>), httpContext); var formatterContext = CreateInputFormatterContext(typeof(List<ComplexModel>), httpContext);
var expectedKey = ReadAsync_ArrayOfObjects_HasCorrectKey_Expected;
// Act // Act
var result = await formatter.ReadAsync(formatterContext); var result = await formatter.ReadAsync(formatterContext);
// Assert // Assert
Assert.True(result.HasError, "Model should have had an error!"); Assert.True(result.HasError, "Model should have had an error!");
Assert.Single(formatterContext.ModelState["[2].Age"].Errors); Assert.Collection(formatterContext.ModelState.OrderBy(k => k.Key),
kvp =>
{
Assert.Equal(expectedKey, kvp.Key);
Assert.Single(kvp.Value.Errors);
});
} }
[Fact] [Fact]
@ -304,13 +297,19 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
var httpContext = GetHttpContext(contentBytes); var httpContext = GetHttpContext(contentBytes);
var formatterContext = CreateInputFormatterContext(typeof(ComplexModel), httpContext); var formatterContext = CreateInputFormatterContext(typeof(ComplexModel), httpContext);
var expectedKey = ReadAsync_AddsModelValidationErrorsToModelState_Expected;
// Act // Act
var result = await formatter.ReadAsync(formatterContext); var result = await formatter.ReadAsync(formatterContext);
// Assert // Assert
Assert.True(result.HasError, "Model should have had an error!"); Assert.True(result.HasError, "Model should have had an error!");
Assert.Single(formatterContext.ModelState["Age"].Errors); Assert.Collection(formatterContext.ModelState.OrderBy(k => k.Key),
kvp =>
{
Assert.Equal(expectedKey, kvp.Key);
Assert.Single(kvp.Value.Errors);
});
} }
[Fact] [Fact]
@ -325,12 +324,17 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
var formatterContext = CreateInputFormatterContext(typeof(short[]), httpContext); var formatterContext = CreateInputFormatterContext(typeof(short[]), httpContext);
var expectedValue = ReadAsync_InvalidArray_AddsOverflowErrorsToModelState_Expected;
// Act // Act
var result = await formatter.ReadAsync(formatterContext); var result = await formatter.ReadAsync(formatterContext);
// Assert // Assert
Assert.True(result.HasError, "Model should have produced an error!"); Assert.True(result.HasError, "Model should have produced an error!");
Assert.True(formatterContext.ModelState.ContainsKey("[2]"), "Should have contained key '[2]'"); Assert.Collection(formatterContext.ModelState.OrderBy(k => k.Key),
kvp => {
Assert.Equal(expectedValue, kvp.Key);
});
} }
[Fact] [Fact]
@ -344,6 +348,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
var httpContext = GetHttpContext(contentBytes); var httpContext = GetHttpContext(contentBytes);
var formatterContext = CreateInputFormatterContext(typeof(ComplexModel[]), httpContext, modelName: "names"); var formatterContext = CreateInputFormatterContext(typeof(ComplexModel[]), httpContext, modelName: "names");
var expectedKey = ReadAsync_InvalidComplexArray_AddsOverflowErrorsToModelState_Expected;
// Act // Act
var result = await formatter.ReadAsync(formatterContext); var result = await formatter.ReadAsync(formatterContext);
@ -353,7 +358,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
Assert.Collection( Assert.Collection(
formatterContext.ModelState.OrderBy(k => k.Key), formatterContext.ModelState.OrderBy(k => k.Key),
kvp => { kvp => {
Assert.Equal("names[1].Small", kvp.Key); Assert.Equal(expectedKey, kvp.Key);
Assert.Single(kvp.Value.Errors); Assert.Single(kvp.Value.Errors);
}); });
} }
@ -424,12 +429,18 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
var formatterContext = CreateInputFormatterContext(typeof(ComplexPoco), httpContext); var formatterContext = CreateInputFormatterContext(typeof(ComplexPoco), httpContext);
var expectedKey = ReadAsync_ComplexPoco_Expected;
// Act // Act
var result = await formatter.ReadAsync(formatterContext); var result = await formatter.ReadAsync(formatterContext);
// Assert // Assert
Assert.True(result.HasError, "Model should have had an error!"); Assert.True(result.HasError, "Model should have had an error!");
Assert.Single(formatterContext.ModelState["Person.Numbers[2]"].Errors); Assert.Collection(formatterContext.ModelState.OrderBy(k => k.Key),
kvp => {
Assert.Equal(expectedKey, kvp.Key);
Assert.Single(kvp.Value.Errors);
});
} }
[Fact] [Fact]
@ -451,6 +462,20 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
Assert.Single(formatterContext.ModelState["Person.Name"].Errors); Assert.Single(formatterContext.ModelState["Person.Name"].Errors);
} }
internal abstract string JsonFormatter_EscapedKeys_Bracket_Expected { get; }
internal abstract string JsonFormatter_EscapedKeys_Expected { get; }
internal abstract string ReadAsync_ArrayOfObjects_HasCorrectKey_Expected { get; }
internal abstract string ReadAsync_AddsModelValidationErrorsToModelState_Expected { get; }
internal abstract string ReadAsync_InvalidArray_AddsOverflowErrorsToModelState_Expected { get; }
internal abstract string ReadAsync_InvalidComplexArray_AddsOverflowErrorsToModelState_Expected { get; }
internal abstract string ReadAsync_ComplexPoco_Expected { get; }
protected abstract TextInputFormatter GetInputFormatter(); protected abstract TextInputFormatter GetInputFormatter();
protected static HttpContext GetHttpContext( protected static HttpContext GetHttpContext(

View File

@ -13,8 +13,6 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{ {
public class SystemTextJsonInputFormatterTest : JsonInputFormatterTestBase public class SystemTextJsonInputFormatterTest : JsonInputFormatterTestBase
{ {
internal override Formatter CurrentFormatter => Formatter.SystemText;
[Fact] [Fact]
public override Task ReadAsync_AddsModelValidationErrorsToModelState() public override Task ReadAsync_AddsModelValidationErrorsToModelState()
{ {
@ -46,6 +44,18 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
throw new NotImplementedException(); throw new NotImplementedException();
} }
[Fact]
public override Task JsonFormatter_EscapedKeys()
{
return base.JsonFormatter_EscapedKeys();
}
[Fact]
public override Task JsonFormatter_EscapedKeys_Bracket()
{
return base.JsonFormatter_EscapedKeys_Bracket();
}
[Fact] [Fact]
public async Task ReadAsync_SingleError() public async Task ReadAsync_SingleError()
{ {
@ -65,7 +75,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
formatterContext.ModelState.OrderBy(k => k), formatterContext.ModelState.OrderBy(k => k),
kvp => kvp =>
{ {
Assert.Equal("[1]", kvp.Key); Assert.Equal("$[1]", kvp.Key);
var error = Assert.Single(kvp.Value.Errors); var error = Assert.Single(kvp.Value.Errors);
Assert.StartsWith("''' is an invalid start of a value", error.ErrorMessage); Assert.StartsWith("''' is an invalid start of a value", error.ErrorMessage);
}); });
@ -75,5 +85,19 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{ {
return new SystemTextJsonInputFormatter(new JsonOptions(), LoggerFactory.CreateLogger<SystemTextJsonInputFormatter>()); return new SystemTextJsonInputFormatter(new JsonOptions(), LoggerFactory.CreateLogger<SystemTextJsonInputFormatter>());
} }
internal override string ReadAsync_AddsModelValidationErrorsToModelState_Expected => "$.Age";
internal override string JsonFormatter_EscapedKeys_Expected => "$[0]['It\\u0022s a key']";
internal override string JsonFormatter_EscapedKeys_Bracket_Expected => "$[0]['It[s a key']";
internal override string ReadAsync_ArrayOfObjects_HasCorrectKey_Expected => "$[2].Age";
internal override string ReadAsync_InvalidArray_AddsOverflowErrorsToModelState_Expected => "$[2]";
internal override string ReadAsync_InvalidComplexArray_AddsOverflowErrorsToModelState_Expected => "$[1].Small";
internal override string ReadAsync_ComplexPoco_Expected => "$.Person.Numbers[2]";
} }
} }

View File

@ -24,8 +24,6 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
private static readonly ObjectPoolProvider _objectPoolProvider = new DefaultObjectPoolProvider(); private static readonly ObjectPoolProvider _objectPoolProvider = new DefaultObjectPoolProvider();
private static readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings(); private static readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings();
internal override Formatter CurrentFormatter => Formatter.Newtonsoft;
[Fact] [Fact]
public async Task Constructor_BuffersRequestBody_UsingDefaultOptions() public async Task Constructor_BuffersRequestBody_UsingDefaultOptions()
{ {
@ -198,6 +196,18 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
Assert.Equal(settings.DateTimeZoneHandling, actual.DateTimeZoneHandling); Assert.Equal(settings.DateTimeZoneHandling, actual.DateTimeZoneHandling);
} }
[Fact]
public override Task JsonFormatter_EscapedKeys()
{
return base.JsonFormatter_EscapedKeys();
}
[Fact]
public override Task JsonFormatter_EscapedKeys_Bracket()
{
return base.JsonFormatter_EscapedKeys_Bracket();
}
[Theory] [Theory]
[InlineData(" ", true, true)] [InlineData(" ", true, true)]
[InlineData(" ", false, false)] [InlineData(" ", false, false)]
@ -360,6 +370,20 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
}); });
} }
internal override string JsonFormatter_EscapedKeys_Expected => "[0]['It\"s a key']";
internal override string JsonFormatter_EscapedKeys_Bracket_Expected => "[0][\'It[s a key\']";
internal override string ReadAsync_AddsModelValidationErrorsToModelState_Expected => "Age";
internal override string ReadAsync_ArrayOfObjects_HasCorrectKey_Expected => "[2].Age";
internal override string ReadAsync_ComplexPoco_Expected => "Person.Numbers[2]";
internal override string ReadAsync_InvalidComplexArray_AddsOverflowErrorsToModelState_Expected => "names[1].Small";
internal override string ReadAsync_InvalidArray_AddsOverflowErrorsToModelState_Expected => "[2]";
private class Location private class Location
{ {
public int Id { get; set; } public int Id { get; set; }