diff --git a/CodeLineCounter.Tests/HashUtilsMockTests.cs b/CodeLineCounter.Tests/HashUtilsMockTests.cs new file mode 100644 index 0000000..fd269d6 --- /dev/null +++ b/CodeLineCounter.Tests/HashUtilsMockTests.cs @@ -0,0 +1,44 @@ +using CodeLineCounter.Utils; +using Moq; + +namespace CodeLineCounter.Tests +{ + public class HashUtilsMockTests : TestBase + { + private readonly Mock _mockHashUtils; + private readonly IHashUtils _originalImplementation; + + public HashUtilsMockTests() + { + _originalImplementation = HashUtils.Implementation; + _mockHashUtils = new Mock(); + HashUtils.Implementation = _mockHashUtils.Object; + } + protected override void Dispose(bool disposing) + { + if (disposing) + { + HashUtils.Implementation = _originalImplementation; + } + + base.Dispose(disposing); + + } + + [Fact] + public void ComputeHash_WithMockedImplementation_CallsMockMethod() + { + // Arrange + string input = "Test"; + string expected = "mocked-hash"; + _mockHashUtils.Setup(m => m.ComputeHash(input)).Returns(expected); + + // Act + string result = HashUtils.ComputeHash(input); + + // Assert + Assert.Equal(expected, result); + _mockHashUtils.Verify(m => m.ComputeHash(input), Times.Once); + } + } +} \ No newline at end of file diff --git a/CodeLineCounter.Tests/HashUtilsServiceTests.cs b/CodeLineCounter.Tests/HashUtilsServiceTests.cs new file mode 100644 index 0000000..655147f --- /dev/null +++ b/CodeLineCounter.Tests/HashUtilsServiceTests.cs @@ -0,0 +1,69 @@ +using CodeLineCounter.Utils; + +namespace CodeLineCounter.Tests +{ + public class HashUtilsServiceTests + { + private readonly HashUtilsService _hashUtils; + + public HashUtilsServiceTests() + { + _hashUtils = new HashUtilsService(); + } + + [Fact] + public void ComputeHash_EmptyString_ReturnsEmptyString() + { + // Arrange + string input = ""; + + // Act + string result = _hashUtils.ComputeHash(input); + + // Assert + Assert.Equal("", result); + } + + [Fact] + public void ComputeHash_NullString_ReturnsEmptyString() + { + // Arrange + string? input = null; + + // Act + string result = _hashUtils.ComputeHash(input); + + // Assert + Assert.Equal("", result); + } + + [Fact] + public void ComputeHash_ValidString_ReturnsHash() + { + // Arrange + string input = "Hello, World!"; + + // Act + string result = _hashUtils.ComputeHash(input); + + // Assert + Assert.NotEmpty(result); + Assert.IsType(result); + } + + [Fact] + public void ComputeHash_DuplicateStrings_ReturnSameHash() + { + // Arrange + string input1 = "Hello, World!"; + string input2 = "Hello, World!"; + + // Act + string result1 = _hashUtils.ComputeHash(input1); + string result2 = _hashUtils.ComputeHash(input2); + + // Assert + Assert.Equal(result1, result2); + } + } +} \ No newline at end of file diff --git a/CodeLineCounter.Tests/HashUtilsTests.cs b/CodeLineCounter.Tests/HashUtilsTests.cs index e15d2ab..78f16a6 100644 --- a/CodeLineCounter.Tests/HashUtilsTests.cs +++ b/CodeLineCounter.Tests/HashUtilsTests.cs @@ -3,7 +3,7 @@ namespace CodeLineCounter.Tests { public class HashUtilsTests - { + { [Fact] public void ComputeHash_EmptyString_ReturnsEmptyString() { @@ -62,5 +62,13 @@ public void ComputeHash_DuplicateStrings_ReturnSameHash() // Assert Assert.Equal(result1, result2); } + + [Fact] + public void Implementation_IsInitializedByDefault() + { + // Act & Assert + Assert.NotNull(HashUtils.Implementation); + Assert.IsType(HashUtils.Implementation, exactMatch: false); + } } } \ No newline at end of file diff --git a/CodeLineCounter/AssemblyInfo.cs b/CodeLineCounter/AssemblyInfo.cs new file mode 100644 index 0000000..70937a3 --- /dev/null +++ b/CodeLineCounter/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("CodeLineCounter.Tests")] \ No newline at end of file diff --git a/CodeLineCounter/Utils/HashUtils.cs b/CodeLineCounter/Utils/HashUtils.cs index 59349d7..9d8eb22 100644 --- a/CodeLineCounter/Utils/HashUtils.cs +++ b/CodeLineCounter/Utils/HashUtils.cs @@ -5,23 +5,12 @@ namespace CodeLineCounter.Utils { public static class HashUtils { + private static readonly IHashUtils _defaultImplementation = new HashUtilsService(); + + internal static IHashUtils Implementation { get; set; } = _defaultImplementation; public static string ComputeHash(string? input) { - if (string.IsNullOrEmpty(input)) - { - return ""; - } - - byte[] bytes = SHA256.HashData(Encoding.UTF8.GetBytes(input)); - - return string.Create(bytes.Length * 2, bytes, static (span, byteArray) => - { - const string format = "x2"; - for (int i = 0; i < byteArray.Length; i++) - { - byteArray[i].TryFormat(span.Slice(i * 2, 2), out _, format); - } - }); + return Implementation.ComputeHash(input); } } -} +} \ No newline at end of file diff --git a/CodeLineCounter/Utils/HashUtilsService.cs b/CodeLineCounter/Utils/HashUtilsService.cs new file mode 100644 index 0000000..195e68c --- /dev/null +++ b/CodeLineCounter/Utils/HashUtilsService.cs @@ -0,0 +1,27 @@ +using System.Security.Cryptography; +using System.Text; + +namespace CodeLineCounter.Utils +{ + public class HashUtilsService : IHashUtils + { + public string ComputeHash(string? input) + { + if (string.IsNullOrEmpty(input)) + { + return string.Empty; + } + + byte[] bytes = SHA256.HashData(Encoding.UTF8.GetBytes(input)); + + return string.Create(bytes.Length * 2, bytes, static (span, byteArray) => + { + const string format = "x2"; + for (int i = 0; i < byteArray.Length; i++) + { + byteArray[i].TryFormat(span.Slice(i * 2, 2), out _, format); + } + }); + } + } +} \ No newline at end of file diff --git a/CodeLineCounter/Utils/IHashUtils.cs b/CodeLineCounter/Utils/IHashUtils.cs new file mode 100644 index 0000000..060490f --- /dev/null +++ b/CodeLineCounter/Utils/IHashUtils.cs @@ -0,0 +1,7 @@ +namespace CodeLineCounter.Utils +{ + public interface IHashUtils + { + string ComputeHash(string? input); + } +} \ No newline at end of file