问题
In Fluent Assertions when comparing objects with DateTime properties there are sometimes a slight mismatch in the milliseconds and the comparison fail. The way we get around it is to set the comparison option like so:
actual.ShouldBeEquivalentTo(expected,
options =>
options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation))
.WhenTypeIs<DateTime>());
Is there a way to set this up once and have it always apply instead of having to specify it every time we call ShouldBeEquivalentTo?
Update1: Tried the following approach but it doesn't seem to work, test fails on 1 millisecond difference. The new default does not seem to get called by the factory.
using System;
using FluentAssertions;
using FluentAssertions.Equivalency;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject1
{
class Test
{
public DateTime TestDateTime { get; set; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void SettingFluentAssertionDefault()
{
// arrange
var defaultAssertionOptions = EquivalencyAssertionOptions<DateTime>.Default;
EquivalencyAssertionOptions<DateTime>.Default = () =>
{
var config = defaultAssertionOptions();
config.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
return config;
};
var testDateTime = DateTime.Now;
var expected = new Test {TestDateTime = testDateTime};
// act
var actual = new Test {TestDateTime = testDateTime.AddMilliseconds(1)};
// assert
actual.ShouldBeEquivalentTo(expected);
}
}
}
回答1:
Actually, you can. The default configuration factory is exposed by the static
property EquivalencyAssertionOptions<Test>.Default
. You can easily assign an alternative configuration for a particular data type, or extend the default configuration with additional behavior. Something like:
var defaultAssertionOptions = EquivalencyAssertionOptions<Test>.Default;
EquivalencyAssertionOptions<Test>.Default = () =>
{
var config = defaultAssertionOptions();
config.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
return config;
};
If you want you can get the current default and tuck that away in some variable that you use from your factory method.
回答2:
Now this can be done with the AssertionOptions static class. To use a simple example:
[TestInitialize]
public void TestInit() {
AssertionOptions.AssertEquivalencyUsing(options => options.ExcludingMissingMembers());
}
Or as in the example above:
AssertionOptions.AssertEquivalencyUsing(options =>
options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>()
);
回答3:
I am afraid the closest thing you can come to, is providing new methods
public static void ShouldBeEquivalentToDef<T>(this T subject, object expectation, string reason = "",
params object[] reasonArgs)
{
ShouldBeEquivalentToDef(subject, expectation, config => config, reason, reasonArgs);
}
public static void ShouldBeEquivalentToDef<T>(this T subject, object expectation,
Func<EquivalencyAssertionOptions<T>, EquivalencyAssertionOptions<T>> config, string reason = "", params object[] reasonArgs)
{
var context = new EquivalencyValidationContext
{
Subject = subject,
Expectation = expectation,
CompileTimeType = typeof (T),
Reason = reason,
ReasonArgs = reasonArgs
};
var defConstructedOptions = config(EquivalencyAssertionOptions<T>.Default());
defConstructedOptions.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation))
.WhenTypeIs<DateTime>()
new EquivalencyValidator(defConstructedOptions).AssertEquality(context);
}
来源:https://stackoverflow.com/questions/20693872/c-sharp-fluent-assertions-global-options-for-shouldbeequivalentto