diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 469919b..6262d04 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -7,7 +7,7 @@ trigger: variables: BuildConfiguration: Release - DotNetCoreVersion: 6.0.200 + DotNetCoreVersion: 6.0.201 stages: - stage: BuildAndTest diff --git a/global.json b/global.json index 403171d..726ce1b 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "6.0.200" + "version": "6.0.201" } } \ No newline at end of file diff --git a/src/Fluxera.ValueObject/Fluxera.ValueObject.csproj b/src/Fluxera.ValueObject/Fluxera.ValueObject.csproj index 2ad69a6..4559fb3 100644 --- a/src/Fluxera.ValueObject/Fluxera.ValueObject.csproj +++ b/src/Fluxera.ValueObject/Fluxera.ValueObject.csproj @@ -22,8 +22,9 @@ - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Fluxera.ValueObject/PrimitiveValueObject.cs b/src/Fluxera.ValueObject/PrimitiveValueObject.cs new file mode 100644 index 0000000..7441245 --- /dev/null +++ b/src/Fluxera.ValueObject/PrimitiveValueObject.cs @@ -0,0 +1,43 @@ +namespace Fluxera.ValueObject +{ + using System; + using System.Collections.Generic; + using Fluxera.Guards; + using Fluxera.Utilities.Extensions; + using JetBrains.Annotations; + + /// + /// A base class for a value object that only contains a single primitive value. + /// + /// + /// The following types are allowed to be used with this class: + /// Any type that returns truef or and + /// additionally values, , , + /// , , and . + /// + /// The type of the value object. + /// The type of the value. + [PublicAPI] + public abstract class PrimitiveValueObject : ValueObject + where TValueObject : ValueObject + { + static PrimitiveValueObject() + { + Type valueType = typeof(TValue); + bool isPrimitive = valueType.IsPrimitive(true, true); + + Guard.Against.False(isPrimitive, nameof(Value), "The value of a primitive value object must be a primitive, string or enum value."); + } + + /// + /// Gets or sets the single value of the value object. + /// + public TValue? Value { get; set; } + + /// + protected sealed override IEnumerable GetEqualityComponents() + { + yield return this.Value; + } + } +} diff --git a/src/Fluxera.ValueObject/ValueObject.cs b/src/Fluxera.ValueObject/ValueObject.cs index 8086da8..82cc796 100644 --- a/src/Fluxera.ValueObject/ValueObject.cs +++ b/src/Fluxera.ValueObject/ValueObject.cs @@ -6,7 +6,7 @@ using JetBrains.Annotations; /// - /// A base class for any value object. + /// A base class for any value object. /// /// The type of the value object. [PublicAPI] @@ -14,17 +14,20 @@ public abstract class ValueObject where TValueObject : ValueObject { /// - /// To ensure hashcode uniqueness, a carefully selected random number multiplier - /// is used within the calculation. + /// To ensure hashcode uniqueness, a carefully selected random number multiplier + /// is used within the calculation. /// /// - /// See http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/ + /// See http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/ /// private const int HashMultiplier = 37; + /// + /// Checks if the given value objects are equal. + /// public static bool operator ==(ValueObject? left, ValueObject? right) { - if (left is null) + if(left is null) { return right is null; } @@ -32,32 +35,35 @@ public abstract class ValueObject return left.Equals(right); } + /// + /// Checks if the given value objects are not equal. + /// public static bool operator !=(ValueObject? left, ValueObject? right) { return !(left == right); } /// - public override bool Equals(object? obj) + public sealed override bool Equals(object? obj) { if(obj is null) { return false; } - if (object.ReferenceEquals(this, obj)) + if(object.ReferenceEquals(this, obj)) { return true; } ValueObject? other = obj as ValueObject; - return other != null - && this.GetType() == other.GetType() + return (other != null) + && (this.GetType() == other.GetType()) && this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); } /// - public override int GetHashCode() + public sealed override int GetHashCode() { unchecked { @@ -79,7 +85,7 @@ public override int GetHashCode() } /// - public override string ToString() + public sealed override string ToString() { using(IEnumerator enumerator = this.GetEqualityComponents().GetEnumerator()) { @@ -94,6 +100,7 @@ public override string ToString() { builder.Append(" ,").Append(enumerator.Current); } + builder.Append(" }"); return builder.ToString(); @@ -101,9 +108,9 @@ public override string ToString() } /// - /// Gets all components of the value object that are used for equality.
- /// The default implementation get all properties via reflection. One - /// can at any time override this behavior with a manual or custom implementation. + /// Gets all components of the value object that are used for equality.
+ /// The default implementation get all properties via reflection. One + /// can at any time override this behavior with a manual or custom implementation. ///
/// The components to use for equality. protected virtual IEnumerable GetEqualityComponents() diff --git a/tests/Fluxera.ValueObject.UnitTests/EqualsOperatorsTests.cs b/tests/Fluxera.ValueObject.UnitTests/EqualsOperatorsTests.cs index 62a08d0..d8a3098 100644 --- a/tests/Fluxera.ValueObject.UnitTests/EqualsOperatorsTests.cs +++ b/tests/Fluxera.ValueObject.UnitTests/EqualsOperatorsTests.cs @@ -2,49 +2,135 @@ { using System.Collections.Generic; using FluentAssertions; - using Model; + using Fluxera.ValueObject.UnitTests.Model; using NUnit.Framework; [TestFixture] public class EqualsOperatorsTests { - [Test] - [TestCaseSource(nameof(OperatorTestData))] - public void EqualOperatorShouldReturnExpectedValue(Address first, Address second, bool expected) + private static IEnumerable OperatorTestData = new List + { + new object[] + { + null!, + null!, + true + }, + new object[] + { + new Address("Testgasse", "50", "11111", "Bremen"), + new Address("Testgasse", "50", "11111", "Bremen"), + true + }, + new object[] + { + new Address("Testgasse", "50", "11111", "Bremen"), + new Address("Testweg", "50", "11111", "Bremen"), + false + }, + new object[] + { + new Address("Testgasse", "50", "11111", "Bremen"), + null!, + false + } + }; + + private static IEnumerable OperatorPrimitiveTestData = new List + { + new object[] + { + new PostCode("12345"), + new PostCode("12345"), + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "XYZ" + }, + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("54321") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + false + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("54321") + { + WillNotBeConsideredForEqualityAndHashCode = "XYZ" + }, + false + } + }; + + [Test] + [TestCaseSource(nameof(OperatorPrimitiveTestData))] + public void EqualOperatorPrimitiveShouldReturnExpectedValue(PostCode first, PostCode second, bool expected) { bool result = first == second; result.Should().Be(expected); } - [Test] + [Test] [TestCaseSource(nameof(OperatorTestData))] - public void NotEqualOperatorShouldReturnExpectedValue(Address first, Address second, bool expected) + public void EqualOperatorShouldReturnExpectedValue(Address first, Address second, bool expected) { - bool result = first != second; - result.Should().Be(!expected); + bool result = first == second; + result.Should().Be(expected); } - [Test] - public void EqualOperatorShouldReturnTrueForEmptyValueObject() + [Test] + public void EqualOperatorShouldReturnFalseForDerivedTypes() { - Empty first = new Empty(); - Empty second = new Empty(); + BankAccount first = new BankAccount("Tester", "DE0000000000000", "ABCDFFXXX"); + GermanBankAccount second = new GermanBankAccount("Tester", "DE0000000000000", "ABCDFFXXX"); bool result = first == second; - result.Should().BeTrue(); + result.Should().BeFalse(); } - [Test] - public void EqualOperatorShouldReturnFalseForDerivedTypes() + [Test] + public void EqualOperatorShouldReturnFalseForDerivedTypesWithDifferentData() { - BankAccount first = new BankAccount("Tester", "DE0000000000000", "ABCDFFXXX"); - GermanBankAccount second = new GermanBankAccount("Tester", "DE0000000000000", "ABCDFFXXX"); + GermanBankAccount first = new GermanBankAccount("Tester", "DE0000000000000", "ABCDFFXXX"); + GermanBankAccount second = new GermanBankAccount("Testonius", "DE0000000000000", "ABCDFFXXX"); bool result = first == second; result.Should().BeFalse(); } - [Test] + [Test] public void EqualOperatorShouldReturnTrueForDerivedTypesWithSameData() { GermanBankAccount first = new GermanBankAccount("Tester", "DE0000000000000", "ABCDFFXXX"); @@ -54,45 +140,30 @@ public void EqualOperatorShouldReturnTrueForDerivedTypesWithSameData() result.Should().BeTrue(); } - [Test] - public void EqualOperatorShouldReturnFalseForDerivedTypesWithDifferentData() + [Test] + public void EqualOperatorShouldReturnTrueForEmptyValueObject() { - GermanBankAccount first = new GermanBankAccount("Tester", "DE0000000000000", "ABCDFFXXX"); - GermanBankAccount second = new GermanBankAccount("Testonius", "DE0000000000000", "ABCDFFXXX"); + Empty first = new Empty(); + Empty second = new Empty(); bool result = first == second; - result.Should().BeFalse(); + result.Should().BeTrue(); } - private static IEnumerable OperatorTestData = new List + [Test] + [TestCaseSource(nameof(OperatorTestData))] + public void NotEqualOperatorPrimitiveShouldReturnExpectedValue(Address first, Address second, bool expected) { - new object[] - { - null!, - null!, - true - }, - - new object[] - { - new Address("Testgasse", "50", "11111", "Bremen"), - new Address("Testgasse", "50", "11111", "Bremen"), - true - }, - - new object[] - { - new Address("Testgasse", "50", "11111", "Bremen"), - new Address("Testweg", "50", "11111", "Bremen"), - false - }, + bool result = first != second; + result.Should().Be(!expected); + } - new object[] - { - new Address("Testgasse", "50", "11111", "Bremen"), - null!, - false - }, - }; + [Test] + [TestCaseSource(nameof(OperatorPrimitiveTestData))] + public void NotEqualOperatorShouldReturnExpectedValue(PostCode first, PostCode second, bool expected) + { + bool result = first != second; + result.Should().Be(!expected); + } } } diff --git a/tests/Fluxera.ValueObject.UnitTests/EqualsTests.cs b/tests/Fluxera.ValueObject.UnitTests/EqualsTests.cs index aa66609..531aec9 100644 --- a/tests/Fluxera.ValueObject.UnitTests/EqualsTests.cs +++ b/tests/Fluxera.ValueObject.UnitTests/EqualsTests.cs @@ -2,65 +2,12 @@ { using System.Collections.Generic; using FluentAssertions; - using Microsoft.VisualBasic; - using Model; + using Fluxera.ValueObject.UnitTests.Model; using NUnit.Framework; [TestFixture] public class EqualsTests { - [Test] - [TestCaseSource(nameof(TestData))] - public void EqualShouldReturnExpectedValue(object first, object second, bool expected) - { - bool result = first.Equals(second); - result.Should().Be(expected); - } - - [Test] - public void EqualShouldReturnTrueForCorrectlyImplementedCollections() - { - Confederation confederation1 = new Confederation("European Union", new List - { - Country.Create("FR"), - Country.Create("DE"), - Country.Create("AT"), - // ... - }); - - Confederation confederation2 = new Confederation("European Union", new List - { - Country.Create("FR"), - Country.Create("DE"), - Country.Create("AT"), - // ... - }); - - confederation1.Equals(confederation2).Should().BeTrue(); - } - - [Test] - public void EqualShouldReturnTrueForIncorrectlyImplementedCollections() - { - ConfederationIncorrectImplementation confederation1 = new ConfederationIncorrectImplementation("European Union", new List - { - Country.Create("FR"), - Country.Create("DE"), - Country.Create("AT"), - // ... - }); - - ConfederationIncorrectImplementation confederation2 = new ConfederationIncorrectImplementation("European Union", new List - { - Country.Create("FR"), - Country.Create("DE"), - Country.Create("AT"), - // ... - }); - - confederation1.Equals(confederation2).Should().BeFalse(); - } - private static IEnumerable TestData = new List { new object[] @@ -126,5 +73,116 @@ public void EqualShouldReturnTrueForIncorrectlyImplementedCollections() false }, }; + + private static IEnumerable PrimitiveTestData = new List + { + new object[] + { + new PostCode("12345"), + new PostCode("12345"), + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "XYZ" + }, + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("54321") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + false + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("54321") + { + WillNotBeConsideredForEqualityAndHashCode = "XYZ" + }, + false + } + }; + + [Test] + [TestCaseSource(nameof(TestData))] + [TestCaseSource(nameof(PrimitiveTestData))] + public void EqualShouldReturnExpectedValue(object first, object second, bool expected) + { + bool result = first.Equals(second); + result.Should().Be(expected); + } + + [Test] + public void EqualShouldReturnTrueForCorrectlyImplementedCollections() + { + Confederation confederation1 = new Confederation("European Union", new List + { + Country.Create("FR"), + Country.Create("DE"), + Country.Create("AT"), + // ... + }); + + Confederation confederation2 = new Confederation("European Union", new List + { + Country.Create("FR"), + Country.Create("DE"), + Country.Create("AT"), + // ... + }); + + confederation1.Equals(confederation2).Should().BeTrue(); + } + + [Test] + public void EqualShouldReturnTrueForIncorrectlyImplementedCollections() + { + ConfederationIncorrectImplementation confederation1 = new ConfederationIncorrectImplementation("European Union", new List + { + Country.Create("FR"), + Country.Create("DE"), + Country.Create("AT"), + // ... + }); + + ConfederationIncorrectImplementation confederation2 = new ConfederationIncorrectImplementation("European Union", new List + { + Country.Create("FR"), + Country.Create("DE"), + Country.Create("AT"), + // ... + }); + + confederation1.Equals(confederation2).Should().BeFalse(); + } } } diff --git a/tests/Fluxera.ValueObject.UnitTests/Fluxera.ValueObject.UnitTests.csproj b/tests/Fluxera.ValueObject.UnitTests/Fluxera.ValueObject.UnitTests.csproj index abbf222..56fe848 100644 --- a/tests/Fluxera.ValueObject.UnitTests/Fluxera.ValueObject.UnitTests.csproj +++ b/tests/Fluxera.ValueObject.UnitTests/Fluxera.ValueObject.UnitTests.csproj @@ -13,9 +13,9 @@ - + - + all diff --git a/tests/Fluxera.ValueObject.UnitTests/GetHashCodeTests.cs b/tests/Fluxera.ValueObject.UnitTests/GetHashCodeTests.cs index d8b1f25..346d2d8 100644 --- a/tests/Fluxera.ValueObject.UnitTests/GetHashCodeTests.cs +++ b/tests/Fluxera.ValueObject.UnitTests/GetHashCodeTests.cs @@ -3,21 +3,69 @@ using System; using System.Collections.Generic; using FluentAssertions; - using Model; + using Fluxera.ValueObject.UnitTests.Model; using NUnit.Framework; [TestFixture] public class GetHashCodeTests { - [Test] - [TestCaseSource(nameof(TestData))] - public void GetHashCodeShouldReturnExpectedValue(object first, object second, bool expected) + private static IEnumerable PrimitiveTestData = new List { - Console.WriteLine($"{first.GetHashCode()} : {second.GetHashCode()}"); - - bool result = first.GetHashCode() == second.GetHashCode(); - result.Should().Be(expected); - } + new object[] + { + new PostCode("12345"), + new PostCode("12345"), + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "XYZ" + }, + true + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("54321") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + false + }, + new object[] + { + new PostCode("12345") + { + WillNotBeConsideredForEqualityAndHashCode = "ABC" + }, + new PostCode("54321") + { + WillNotBeConsideredForEqualityAndHashCode = "XYZ" + }, + false + } + }; private static IEnumerable TestData = new List { @@ -77,5 +125,16 @@ public void GetHashCodeShouldReturnExpectedValue(object first, object second, bo false }, }; + + [Test] + [TestCaseSource(nameof(TestData))] + [TestCaseSource(nameof(PrimitiveTestData))] + public void GetHashCodeShouldReturnExpectedValue(object first, object second, bool expected) + { + Console.WriteLine($"{first.GetHashCode()} : {second.GetHashCode()}"); + + bool result = first.GetHashCode() == second.GetHashCode(); + result.Should().Be(expected); + } } } diff --git a/tests/Fluxera.ValueObject.UnitTests/Model/EnumValue.cs b/tests/Fluxera.ValueObject.UnitTests/Model/EnumValue.cs new file mode 100644 index 0000000..ab78106 --- /dev/null +++ b/tests/Fluxera.ValueObject.UnitTests/Model/EnumValue.cs @@ -0,0 +1,9 @@ +namespace Fluxera.ValueObject.UnitTests.Model +{ + using JetBrains.Annotations; + + [PublicAPI] + public class EnumValue : PrimitiveValueObject + { + } +} diff --git a/tests/Fluxera.ValueObject.UnitTests/Model/GuidValue.cs b/tests/Fluxera.ValueObject.UnitTests/Model/GuidValue.cs new file mode 100644 index 0000000..62753c0 --- /dev/null +++ b/tests/Fluxera.ValueObject.UnitTests/Model/GuidValue.cs @@ -0,0 +1,10 @@ +namespace Fluxera.ValueObject.UnitTests.Model +{ + using System; + using JetBrains.Annotations; + + [PublicAPI] + public class GuidValue : PrimitiveValueObject + { + } +} diff --git a/tests/Fluxera.ValueObject.UnitTests/Model/IntValue.cs b/tests/Fluxera.ValueObject.UnitTests/Model/IntValue.cs new file mode 100644 index 0000000..f726509 --- /dev/null +++ b/tests/Fluxera.ValueObject.UnitTests/Model/IntValue.cs @@ -0,0 +1,9 @@ +namespace Fluxera.ValueObject.UnitTests.Model +{ + using JetBrains.Annotations; + + [PublicAPI] + public class IntValue : PrimitiveValueObject + { + } +} diff --git a/tests/Fluxera.ValueObject.UnitTests/Model/InvalidPrimitive.cs b/tests/Fluxera.ValueObject.UnitTests/Model/InvalidPrimitive.cs new file mode 100644 index 0000000..619b654 --- /dev/null +++ b/tests/Fluxera.ValueObject.UnitTests/Model/InvalidPrimitive.cs @@ -0,0 +1,9 @@ +namespace Fluxera.ValueObject.UnitTests.Model +{ + using JetBrains.Annotations; + + [PublicAPI] + public class InvalidPrimitive : PrimitiveValueObject + { + } +} diff --git a/tests/Fluxera.ValueObject.UnitTests/Model/PostCode.cs b/tests/Fluxera.ValueObject.UnitTests/Model/PostCode.cs new file mode 100644 index 0000000..027c43d --- /dev/null +++ b/tests/Fluxera.ValueObject.UnitTests/Model/PostCode.cs @@ -0,0 +1,15 @@ +namespace Fluxera.ValueObject.UnitTests.Model +{ + using JetBrains.Annotations; + + [PublicAPI] + public class PostCode : PrimitiveValueObject + { + public PostCode(string value) + { + this.Value = value; + } + + public string WillNotBeConsideredForEqualityAndHashCode { get; set; } + } +} diff --git a/tests/Fluxera.ValueObject.UnitTests/Model/StringValue.cs b/tests/Fluxera.ValueObject.UnitTests/Model/StringValue.cs new file mode 100644 index 0000000..68a6d80 --- /dev/null +++ b/tests/Fluxera.ValueObject.UnitTests/Model/StringValue.cs @@ -0,0 +1,9 @@ +namespace Fluxera.ValueObject.UnitTests.Model +{ + using JetBrains.Annotations; + + [PublicAPI] + public class StringValue : PrimitiveValueObject + { + } +} diff --git a/tests/Fluxera.ValueObject.UnitTests/PrimitiveValueObjectTests.cs b/tests/Fluxera.ValueObject.UnitTests/PrimitiveValueObjectTests.cs new file mode 100644 index 0000000..47f7a9d --- /dev/null +++ b/tests/Fluxera.ValueObject.UnitTests/PrimitiveValueObjectTests.cs @@ -0,0 +1,34 @@ +namespace Fluxera.ValueObject.UnitTests +{ + using System; + using System.Collections.Generic; + using FluentAssertions; + using Fluxera.ValueObject.UnitTests.Model; + using NUnit.Framework; + + [TestFixture] + public class PrimitiveValueObjectTests + { + private static IEnumerable PrimitiveTestData = new List + { + () => new StringValue(), + () => new IntValue(), + () => new GuidValue(), + () => new EnumValue(), + }; + + [Test] + [TestCaseSource(nameof(PrimitiveTestData))] + public void ShouldNotThrowForValidTypes(Action action) + { + action.Should().NotThrow(); + } + + [Test] + public void ShouldThrowForInvalidTypes() + { + Action action = () => new InvalidPrimitive(); + action.Should().Throw(); + } + } +} diff --git a/tests/Fluxera.ValueObject.UnitTests/ValueObjectExtensionsTests.cs b/tests/Fluxera.ValueObject.UnitTests/ValueObjectExtensionsTests.cs index da52d0e..8ea1e31 100644 --- a/tests/Fluxera.ValueObject.UnitTests/ValueObjectExtensionsTests.cs +++ b/tests/Fluxera.ValueObject.UnitTests/ValueObjectExtensionsTests.cs @@ -2,16 +2,23 @@ { using System; using FluentAssertions; - using Model; + using Fluxera.ValueObject.UnitTests.Model; using NUnit.Framework; [TestFixture] public class ValueObjectExtensionsTests { [Test] - public void ShouldReturnTrueForValueObjectType() + public void ShouldReturnFalseForObjectType() { - Type type = typeof(Country); + Type type = typeof(object); + type.IsValueObject().Should().BeFalse(); + } + + [Test] + public void ShouldReturnTrueForPrimitiveValueObjectType() + { + Type type = typeof(PostCode); type.IsValueObject().Should().BeTrue(); } @@ -23,10 +30,10 @@ public void ShouldReturnTrueForValueObjectDerivedType() } [Test] - public void ShouldReturnFalseForObjectType() + public void ShouldReturnTrueForValueObjectType() { - Type type = typeof(object); - type.IsValueObject().Should().BeFalse(); + Type type = typeof(Country); + type.IsValueObject().Should().BeTrue(); } } }