Serialization settings can be customized at three levels:
- Method: Will run the verification in the current test method.
- Class: Will run for all verifications in all test methods for a test class.
- Global: Will run for test methods on all tests.
- Default settings
- Single quotes used
- QuoteName is false
- Empty collections are ignored
- Guids are scrubbed
- Dates are scrubbed
- Default Booleans are ignored
- Change defaults at the verification level
- Changing settings globally
- Scoped settings
- Ignoring a type
- Ignoring a instance
- Ignore member by expressions
- Ignore member by name
- Members that throw
The default serialization settings are:
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
JsonTextWriter.QuoteChar is set to single quotes '
. The reason for this is that it makes approval files cleaner and easier to read and visualize/understand differences.
JsonTextWriter.QuoteName is set to false. The reason for this is that it makes approval files cleaner and easier to read and visualize/understand differences.
By default empty collections are ignored during verification.
To disable this behavior globally use:
SharedVerifySettings.ModifySerialization(_ => _.DontIgnoreEmptyCollections());
By default guids are sanitized during verification. This is done by finding each guid and taking a counter based that that specific guid. That counter is then used replace the guid values. This allows for repeatable tests when guid values are changing.
var guid = Guid.NewGuid();
var target = new GuidTarget
{
Guid = guid,
GuidNullable = guid,
GuidString = guid.ToString(),
OtherGuid = Guid.NewGuid(),
};
await Verify(target);
Results in the following:
{
Guid: Guid_1,
GuidNullable: Guid_1,
GuidString: Guid_1,
OtherGuid: Guid_2
}
To disable this behavior globally use:
SharedVerifySettings.ModifySerialization(_ => _.DontScrubGuids());
By default dates (DateTime
and DateTimeOffset
) are sanitized during verification. This is done by finding each date and taking a counter based that that specific date. That counter is then used replace the date values. This allows for repeatable tests when date values are changing.
var dateTime = DateTime.Now;
var dateTimeOffset = DateTimeOffset.Now;
var target = new DateTimeTarget
{
DateTime = dateTime,
DateTimeNullable = dateTime,
DateTimeString = dateTime.ToString("F"),
DateTimeOffset = dateTimeOffset,
DateTimeOffsetNullable = dateTimeOffset,
DateTimeOffsetString = dateTimeOffset.ToString("F"),
};
await Verify(target);
Results in the following:
{
DateTime: DateTime_1,
DateTimeNullable: DateTime_1,
DateTimeOffset: DateTimeOffset_1,
DateTimeOffsetNullable: DateTimeOffset_1,
DateTimeString: DateTimeOffset_2,
DateTimeOffsetString: DateTimeOffset_2
}
To disable this behavior globally use:
SharedVerifySettings.ModifySerialization(_ => _.DontScrubDateTimes());
By default values of bool
and bool?
are ignored during verification. So properties that equate to 'false' will not be written,
To disable this behavior globally use:
SharedVerifySettings.ModifySerialization(_ => _.DontIgnoreFalse());
DateTime
, DateTimeOffset
, Guid
, bool
, and empty collection behavior can also be controlled at the verification level:
var settings = new VerifySettings();
settings.ModifySerialization(_ =>
{
_.DontIgnoreEmptyCollections();
_.DontScrubGuids();
_.DontScrubDateTimes();
_.DontIgnoreFalse();
});
await Verify(target, settings);
var settings = new VerifySettings();
settings.ModifySerialization(_ =>
{
_.DontIgnoreEmptyCollections();
_.DontScrubGuids();
_.DontScrubDateTimes();
_.DontIgnoreFalse();
});
await Verifier.Verify(target, settings);
To change the serialization settings for all verifications use Global.ApplyExtraSettings()
:
var settings = new VerifySettings();
settings.AddExtraSettings(_ =>
{
_.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
_.TypeNameHandling = TypeNameHandling.All;
});
var person = new Person
{
GivenNames = "John",
FamilyName = "Smith",
Dob = new DateTimeOffset(2000, 10, 1, 0, 0, 0, TimeSpan.Zero),
};
var settings = new VerifySettings();
settings.ModifySerialization(
_ => _.DontScrubDateTimes());
settings.AddExtraSettings(
_ => { _.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat; });
Result:
{
GivenNames: 'John',
FamilyName: 'Smith',
Dob: '\/Date(970358400000+0000)\/'
}
To ignore all members that match a certain type:
var settings = new VerifySettings();
settings.ModifySerialization(_ => _.IgnoreMembersWithType<ToIgnore>());
var target = new IgnoreTypeTarget
{
ToIgnore = new ToIgnore
{
Property = "Value"
},
ToInclude = new ToInclude
{
Property = "Value"
}
};
await Verify(target, settings);
Result:
{
ToInclude: {
Property: 'Value'
}
}
To ignore instances of a type based on delegate:
var settings = new VerifySettings();
settings.ModifySerialization(
_ => { _.IgnoreInstance<Instance>(x => x.Property == "Ignore"); });
var target = new IgnoreInstanceTarget
{
ToIgnore = new Instance
{
Property = "Ignore"
},
ToInclude = new Instance
{
Property = "Include"
}
};
await Verify(target, settings);
Result:
{
ToInclude: {
Property: 'Include'
}
}
To ignore members of a certain type using an expression:
var settings = new VerifySettings();
settings.ModifySerialization(_ =>
{
_.IgnoreMember<IgnoreExplicitTarget>(x => x.Property);
_.IgnoreMember<IgnoreExplicitTarget>(x => x.Field);
_.IgnoreMember<IgnoreExplicitTarget>(x => x.GetOnlyProperty);
_.IgnoreMember<IgnoreExplicitTarget>(x => x.PropertyThatThrows);
});
var target = new IgnoreExplicitTarget
{
Include = "Value",
Field = "Value",
Property = "Value"
};
await Verify(target, settings);
Result:
{
Include: 'Value'
}
To ignore members of a certain type using type and name:
var settings = new VerifySettings();
settings.ModifySerialization(_ =>
{
var type = typeof(IgnoreExplicitTarget);
_.IgnoreMember(type, "Property");
_.IgnoreMember(type, "Field");
_.IgnoreMember(type, "GetOnlyProperty");
_.IgnoreMember(type, "PropertyThatThrows");
});
var target = new IgnoreExplicitTarget
{
Include = "Value",
Field = "Value",
Property = "Value"
};
await Verify(target, settings);
Result:
{
Include: 'Value'
}
Members that throw exceptions can be excluded from serialization based on the exception type or properties.
By default members that throw NotImplementedException
or NotSupportedException
are ignored.
Note that this is global for all members on all types.
Ignore by exception type:
var settings = new VerifySettings();
settings.ModifySerialization(_ => _.IgnoreMembersThatThrow<CustomException>());
var target = new WithCustomException();
await Verify(target, settings);
Result:
{}
Ignore by exception type and expression:
var settings = new VerifySettings();
settings.ModifySerialization(
_ => _.IgnoreMembersThatThrow<Exception>(x => x.Message == "Ignore"));
var target = new WithExceptionIgnoreMessage();
await Verify(target, settings);
Result:
{}