Skip to content

Commit 8c11145

Browse files
authored
Merge pull request #31 from magic5644/feature-add-hashutils-interface
Implement hashing functionality with IHashUtils interface and service class
2 parents d209732 + 141dace commit 8c11145

File tree

7 files changed

+164
-17
lines changed

7 files changed

+164
-17
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using CodeLineCounter.Utils;
2+
using Moq;
3+
4+
namespace CodeLineCounter.Tests
5+
{
6+
public class HashUtilsMockTests : TestBase
7+
{
8+
private readonly Mock<IHashUtils> _mockHashUtils;
9+
private readonly IHashUtils _originalImplementation;
10+
11+
public HashUtilsMockTests()
12+
{
13+
_originalImplementation = HashUtils.Implementation;
14+
_mockHashUtils = new Mock<IHashUtils>();
15+
HashUtils.Implementation = _mockHashUtils.Object;
16+
}
17+
protected override void Dispose(bool disposing)
18+
{
19+
if (disposing)
20+
{
21+
HashUtils.Implementation = _originalImplementation;
22+
}
23+
24+
base.Dispose(disposing);
25+
26+
}
27+
28+
[Fact]
29+
public void ComputeHash_WithMockedImplementation_CallsMockMethod()
30+
{
31+
// Arrange
32+
string input = "Test";
33+
string expected = "mocked-hash";
34+
_mockHashUtils.Setup(m => m.ComputeHash(input)).Returns(expected);
35+
36+
// Act
37+
string result = HashUtils.ComputeHash(input);
38+
39+
// Assert
40+
Assert.Equal(expected, result);
41+
_mockHashUtils.Verify(m => m.ComputeHash(input), Times.Once);
42+
}
43+
}
44+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using CodeLineCounter.Utils;
2+
3+
namespace CodeLineCounter.Tests
4+
{
5+
public class HashUtilsServiceTests
6+
{
7+
private readonly HashUtilsService _hashUtils;
8+
9+
public HashUtilsServiceTests()
10+
{
11+
_hashUtils = new HashUtilsService();
12+
}
13+
14+
[Fact]
15+
public void ComputeHash_EmptyString_ReturnsEmptyString()
16+
{
17+
// Arrange
18+
string input = "";
19+
20+
// Act
21+
string result = _hashUtils.ComputeHash(input);
22+
23+
// Assert
24+
Assert.Equal("", result);
25+
}
26+
27+
[Fact]
28+
public void ComputeHash_NullString_ReturnsEmptyString()
29+
{
30+
// Arrange
31+
string? input = null;
32+
33+
// Act
34+
string result = _hashUtils.ComputeHash(input);
35+
36+
// Assert
37+
Assert.Equal("", result);
38+
}
39+
40+
[Fact]
41+
public void ComputeHash_ValidString_ReturnsHash()
42+
{
43+
// Arrange
44+
string input = "Hello, World!";
45+
46+
// Act
47+
string result = _hashUtils.ComputeHash(input);
48+
49+
// Assert
50+
Assert.NotEmpty(result);
51+
Assert.IsType<string>(result);
52+
}
53+
54+
[Fact]
55+
public void ComputeHash_DuplicateStrings_ReturnSameHash()
56+
{
57+
// Arrange
58+
string input1 = "Hello, World!";
59+
string input2 = "Hello, World!";
60+
61+
// Act
62+
string result1 = _hashUtils.ComputeHash(input1);
63+
string result2 = _hashUtils.ComputeHash(input2);
64+
65+
// Assert
66+
Assert.Equal(result1, result2);
67+
}
68+
}
69+
}

CodeLineCounter.Tests/HashUtilsTests.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace CodeLineCounter.Tests
44
{
55
public class HashUtilsTests
6-
{
6+
{
77
[Fact]
88
public void ComputeHash_EmptyString_ReturnsEmptyString()
99
{
@@ -62,5 +62,13 @@ public void ComputeHash_DuplicateStrings_ReturnSameHash()
6262
// Assert
6363
Assert.Equal(result1, result2);
6464
}
65+
66+
[Fact]
67+
public void Implementation_IsInitializedByDefault()
68+
{
69+
// Act & Assert
70+
Assert.NotNull(HashUtils.Implementation);
71+
Assert.IsType<IHashUtils>(HashUtils.Implementation, exactMatch: false);
72+
}
6573
}
6674
}

CodeLineCounter/AssemblyInfo.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using System.Runtime.CompilerServices;
2+
3+
[assembly: InternalsVisibleTo("CodeLineCounter.Tests")]

CodeLineCounter/Utils/HashUtils.cs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,12 @@ namespace CodeLineCounter.Utils
55
{
66
public static class HashUtils
77
{
8+
private static readonly IHashUtils _defaultImplementation = new HashUtilsService();
9+
10+
internal static IHashUtils Implementation { get; set; } = _defaultImplementation;
811
public static string ComputeHash(string? input)
912
{
10-
if (string.IsNullOrEmpty(input))
11-
{
12-
return "";
13-
}
14-
15-
byte[] bytes = SHA256.HashData(Encoding.UTF8.GetBytes(input));
16-
17-
return string.Create(bytes.Length * 2, bytes, static (span, byteArray) =>
18-
{
19-
const string format = "x2";
20-
for (int i = 0; i < byteArray.Length; i++)
21-
{
22-
byteArray[i].TryFormat(span.Slice(i * 2, 2), out _, format);
23-
}
24-
});
13+
return Implementation.ComputeHash(input);
2514
}
2615
}
27-
}
16+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Security.Cryptography;
2+
using System.Text;
3+
4+
namespace CodeLineCounter.Utils
5+
{
6+
public class HashUtilsService : IHashUtils
7+
{
8+
public string ComputeHash(string? input)
9+
{
10+
if (string.IsNullOrEmpty(input))
11+
{
12+
return string.Empty;
13+
}
14+
15+
byte[] bytes = SHA256.HashData(Encoding.UTF8.GetBytes(input));
16+
17+
return string.Create(bytes.Length * 2, bytes, static (span, byteArray) =>
18+
{
19+
const string format = "x2";
20+
for (int i = 0; i < byteArray.Length; i++)
21+
{
22+
byteArray[i].TryFormat(span.Slice(i * 2, 2), out _, format);
23+
}
24+
});
25+
}
26+
}
27+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace CodeLineCounter.Utils
2+
{
3+
public interface IHashUtils
4+
{
5+
string ComputeHash(string? input);
6+
}
7+
}

0 commit comments

Comments
 (0)