Skip to content

Commit 99eb9ff

Browse files
committed
Fix HashCode bug + added unit tests
1 parent d4190e1 commit 99eb9ff

File tree

7 files changed

+157
-8
lines changed

7 files changed

+157
-8
lines changed

GitVersion.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mode: ContinuousDelivery
2-
next-version: 1.0.0
2+
next-version: 1.0.1
33
branches: {}
44
ignore:
55
sha: []

Src/Xer.DomainDriven/ValueObject.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,19 @@ protected struct HashCode
107107
/// <param name="fields">Value object fields.</param>
108108
private HashCode(object[] fields)
109109
{
110+
if (fields == null)
111+
{
112+
throw new ArgumentNullException(nameof(fields));
113+
}
114+
115+
if (fields.Length == 0)
116+
_value = 0;
117+
110118
unchecked
111119
{
112-
int hash = fields.Length > 0 ? 19 : 0;
120+
int hash = 19;
113121

114-
for (int i = 0; fields.Length > 0; i++)
122+
for (int i = 0; fields.Length > i; i++)
115123
{
116124
hash = hash * 486187739 + fields[i]?.GetHashCode() ?? throw new ArgumentException("Cannot pass null as field.", nameof(fields));
117125
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace Xer.DomainDriven.Tests.Entities
2+
{
3+
public class TestValueObject : ValueObject<TestValueObject>
4+
{
5+
public string Data { get; }
6+
public int Number { get; }
7+
8+
public TestValueObject(string data, int number)
9+
{
10+
Data = data;
11+
Number = number;
12+
}
13+
14+
protected override bool ValueEquals(TestValueObject other)
15+
{
16+
return Data == other.Data &&
17+
Number == other.Number;
18+
}
19+
20+
protected override HashCode GenerateHashCode()
21+
{
22+
return HashCode.From(Number, Data);
23+
}
24+
}
25+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using Xer.DomainDriven.Tests.Entities;
2+
using Xunit;
3+
4+
namespace Xer.DomainDriven.Tests
5+
{
6+
public class ValueObjectTests
7+
{
8+
public class EqualsMethod
9+
{
10+
[Fact]
11+
public void ShouldBeTrueIfValueObjectsMatchByValue()
12+
{
13+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
14+
TestValueObject valueObject2 = new TestValueObject("Test", 123);
15+
16+
Assert.True(valueObject1 == valueObject2);
17+
}
18+
19+
[Fact]
20+
public void ShouldNotBeTrueIfValueObjectsDoNotMatchByValue()
21+
{
22+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
23+
TestValueObject valueObject2 = new TestValueObject("Test2", 1234);
24+
25+
Assert.True(valueObject1 != valueObject2);
26+
}
27+
28+
[Fact]
29+
public void ShouldNotBeTrueIfComparedWithNull()
30+
{
31+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
32+
TestValueObject valueObject2 = null;
33+
34+
Assert.True(valueObject1 != valueObject2);
35+
}
36+
}
37+
38+
public class GetHashCodeMethod
39+
{
40+
[Fact]
41+
public void ShouldBeSameForTheSameInstance()
42+
{
43+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
44+
45+
Assert.True(valueObject1.GetHashCode() == valueObject1.GetHashCode());
46+
}
47+
48+
[Fact]
49+
public void ShouldBeSameForTheDifferentInstancesWithSameValues()
50+
{
51+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
52+
TestValueObject valueObject2 = new TestValueObject("Test", 123);
53+
54+
Assert.True(valueObject1.GetHashCode() == valueObject2.GetHashCode());
55+
}
56+
57+
[Fact]
58+
public void ShouldNotBeSameForTheDifferentInstancesWithDifferentValues()
59+
{
60+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
61+
TestValueObject valueObject2 = new TestValueObject("Test2", 1234);
62+
63+
Assert.True(valueObject1.GetHashCode() != valueObject2.GetHashCode());
64+
}
65+
}
66+
}
67+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp2.0</TargetFramework>
5+
6+
<IsPackable>false</IsPackable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
11+
<PackageReference Include="xunit" Version="2.3.1" />
12+
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
13+
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\..\Src\Xer.DomainDriven\Xer.DomainDriven.csproj" />
18+
</ItemGroup>
19+
20+
</Project>

Xer.DomainDriven.sln

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ VisualStudioVersion = 15.0.26124.0
55
MinimumVisualStudioVersion = 15.0.26124.0
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xer.DomainDriven", "Src\Xer.DomainDriven\Xer.DomainDriven.csproj", "{B158F4B9-C157-411A-85FB-3F538432A92F}"
77
EndProject
8+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{77122373-243D-48F3-A0DF-84F83D9467B2}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xer.DomainDriven.Tests", "Tests\Xer.DomainDriven.Tests\Xer.DomainDriven.Tests.csproj", "{544D41FE-8042-40CC-A068-4ED39E519D9D}"
11+
EndProject
812
Global
913
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1014
Debug|Any CPU = Debug|Any CPU
@@ -30,5 +34,20 @@ Global
3034
{B158F4B9-C157-411A-85FB-3F538432A92F}.Release|x64.Build.0 = Release|x64
3135
{B158F4B9-C157-411A-85FB-3F538432A92F}.Release|x86.ActiveCfg = Release|x86
3236
{B158F4B9-C157-411A-85FB-3F538432A92F}.Release|x86.Build.0 = Release|x86
37+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
39+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Debug|x64.ActiveCfg = Debug|x64
40+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Debug|x64.Build.0 = Debug|x64
41+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Debug|x86.ActiveCfg = Debug|x86
42+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Debug|x86.Build.0 = Debug|x86
43+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
44+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Release|Any CPU.Build.0 = Release|Any CPU
45+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Release|x64.ActiveCfg = Release|x64
46+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Release|x64.Build.0 = Release|x64
47+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Release|x86.ActiveCfg = Release|x86
48+
{544D41FE-8042-40CC-A068-4ED39E519D9D}.Release|x86.Build.0 = Release|x86
49+
EndGlobalSection
50+
GlobalSection(NestedProjects) = preSolution
51+
{544D41FE-8042-40CC-A068-4ED39E519D9D} = {77122373-243D-48F3-A0DF-84F83D9467B2}
3352
EndGlobalSection
3453
EndGlobal

build.cake

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var configuration = Argument<string>("configuration", "Release");
1717

1818
var solutions = GetFiles("./**/*.sln");
1919
var projects = GetFiles("./**/*.csproj").Select(x => x.GetDirectory());
20+
string buildArtifactsDirectory = "./BuildArtifacts";
2021

2122
GitVersion gitVersion;
2223

@@ -46,6 +47,13 @@ Setup(context =>
4647
Information("Publish to myget: {0}", BuildParameters.Instance.ShouldPublishMyGet);
4748
Information("Publish to nuget: {0}", BuildParameters.Instance.ShouldPublishNuGet);
4849
Information("///////////////////////////////////////////////////////////////////////////////");
50+
51+
if (DirectoryExists(buildArtifactsDirectory))
52+
{
53+
// Cleanup build artifacts.
54+
Information($"Cleaning up {buildArtifactsDirectory} directory.");
55+
DeleteDirectory(buildArtifactsDirectory, new DeleteDirectorySettings { Recursive = true });
56+
}
4957
});
5058

5159
Teardown(context =>
@@ -164,7 +172,7 @@ Task("Pack")
164172
.IsDependentOn("Test")
165173
.Does(() =>
166174
{
167-
var projects = GetFiles("./src/**/*.csproj");
175+
var projects = GetFiles("./Src/**/*.csproj");
168176

169177
if (projects.Count() == 0)
170178
{
@@ -174,9 +182,9 @@ Task("Pack")
174182

175183
var settings = new DotNetCorePackSettings
176184
{
177-
OutputDirectory = "./BuildArtifacts",
178-
NoBuild = true,
185+
OutputDirectory = buildArtifactsDirectory,
179186
Configuration = configuration,
187+
NoBuild = true,
180188
ArgumentCustomization = (args) => args
181189
.Append("/p:Version={0}", gitVersion.LegacySemVerPadded)
182190
.Append("/p:AssemblyVersion={0}", gitVersion.MajorMinorPatch)
@@ -195,7 +203,8 @@ Task("PublishMyGet")
195203
.IsDependentOn("Pack")
196204
.Does(() =>
197205
{
198-
var nupkgs = GetFiles("./**/*.nupkg");
206+
// Nupkgs in BuildArtifacts folder.
207+
var nupkgs = GetFiles(buildArtifactsDirectory + "/*.nupkg");
199208

200209
if (nupkgs.Count() == 0)
201210
{
@@ -220,7 +229,8 @@ Task("PublishNuGet")
220229
.IsDependentOn("Pack")
221230
.Does(() =>
222231
{
223-
var nupkgs = GetFiles("./**/*.nupkg");
232+
// Nupkgs in BuildArtifacts folder.
233+
var nupkgs = GetFiles(buildArtifactsDirectory + "/*.nupkg");
224234

225235
if (nupkgs.Count() == 0)
226236
{

0 commit comments

Comments
 (0)