-
-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(unit-tests): increase code coverage #252
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
This commit adds: - Improvements to existing unit test code - Improvements to existing unit test naming - Unit tests for `EFCacheKeyPrefixProvider` class - Unit tests for `EFCacheKeyProvider` class - Unit tests for `EFCacheKey` class - Unit tests for `EFCacheServiceCheck` class - Unit tests for `EFDataReaderLoader` class - Unit tests for `EFDebugLogger` class - Unit tests for `EFServiceCollectionExtensions` class - Unit tests for `LockProvider` class - Unit tests for `StringExtensions` class - Unit tests for `TableEntityInfo` class - Unit tests for `XxHash64Unsafe` class
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using Microsoft.Extensions.Options; | ||
using Moq; | ||
|
||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
// ReSharper disable once InconsistentNaming | ||
public class EFCacheKeyPrefixProviderTests | ||
{ | ||
[Fact] | ||
public void Constructor_ThrowsArgumentNullException_WhenCacheSettingsIsNull() | ||
{ | ||
// Arrange | ||
var serviceProvider = new Mock<IServiceProvider>().Object; | ||
|
||
// ReSharper disable once ObjectCreationAsStatement | ||
void Act() => new EFCacheKeyPrefixProvider(serviceProvider, null!); | ||
|
||
// Act && Assert | ||
Assert.Throws<ArgumentNullException>("cacheSettings", Act); | ||
} | ||
|
||
[Fact] | ||
public void GetCacheKeyPrefix_ReturnsCacheKeyPrefixSelectorResult_WhenSelectorIsNotNull() | ||
{ | ||
// Arrange | ||
var serviceProvider = new Mock<IServiceProvider>().Object; | ||
var cacheSettings = Options.Create(new EFCoreSecondLevelCacheSettings | ||
{ | ||
CacheKeyPrefixSelector = _ => "CustomPrefix" | ||
}); | ||
|
||
var provider = new EFCacheKeyPrefixProvider(serviceProvider, cacheSettings); | ||
|
||
// Act | ||
var actual = provider.GetCacheKeyPrefix(); | ||
|
||
// Assert | ||
Assert.Equal("CustomPrefix", actual); | ||
} | ||
|
||
[Fact] | ||
public void GetCacheKeyPrefix_ReturnsCacheKeyPrefix_WhenSelectorIsNull() | ||
{ | ||
// Arrange | ||
var serviceProvider = new Mock<IServiceProvider>().Object; | ||
var cacheSettings = Options.Create(new EFCoreSecondLevelCacheSettings | ||
{ | ||
CacheKeyPrefix = "DefaultPrefix", | ||
CacheKeyPrefixSelector = null | ||
}); | ||
|
||
var provider = new EFCacheKeyPrefixProvider(serviceProvider, cacheSettings); | ||
|
||
// Act | ||
var actual = provider.GetCacheKeyPrefix(); | ||
|
||
// Assert | ||
Assert.Equal("DefaultPrefix", actual); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,294 @@ | ||
using System.Data; | ||
using System.Data.Common; | ||
using System.Diagnostics.CodeAnalysis; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
using Moq; | ||
using Moq.Protected; | ||
|
||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
// ReSharper disable once InconsistentNaming | ||
public class EFCacheKeyProviderTests | ||
{ | ||
private readonly Mock<IEFCacheDependenciesProcessor> _cacheDependenciesProcessorMock; | ||
private readonly Mock<IEFCacheKeyPrefixProvider> _cacheKeyPrefixProviderMock; | ||
private readonly Mock<IEFHashProvider> _hashProviderMock; | ||
private readonly Mock<IEFDebugLogger> _loggerMock; | ||
private readonly IEFCacheKeyProvider _cacheKeyProvider; | ||
|
||
public EFCacheKeyProviderTests() | ||
{ | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
var settings = new EFCoreSecondLevelCacheSettings(); | ||
var cachePolicyParserMock = new Mock<IEFCachePolicyParser>(); | ||
var keyProviderLoggerMock = new Mock<ILogger<EFCacheKeyProvider>>(); | ||
|
||
_cacheDependenciesProcessorMock = new Mock<IEFCacheDependenciesProcessor>(); | ||
_cacheKeyPrefixProviderMock = new Mock<IEFCacheKeyPrefixProvider>(); | ||
_hashProviderMock = new Mock<IEFHashProvider>(); | ||
_loggerMock = new Mock<IEFDebugLogger>(); | ||
|
||
cacheSettingsMock.Setup(c => c.Value).Returns(settings); | ||
|
||
_cacheKeyProvider = new EFCacheKeyProvider( | ||
_cacheDependenciesProcessorMock.Object, | ||
cachePolicyParserMock.Object, | ||
_loggerMock.Object, | ||
keyProviderLoggerMock.Object, | ||
_hashProviderMock.Object, | ||
_cacheKeyPrefixProviderMock.Object, | ||
cacheSettingsMock.Object); | ||
} | ||
|
||
[Fact] | ||
public void EFCacheKeyProvider_ThrowsArgumentNullException_WhenHashProviderIsNull() | ||
{ | ||
// Arrange | ||
var cacheDependenciesProcessorMock = new Mock<IEFCacheDependenciesProcessor>(); | ||
var cachePolicyParserMock = new Mock<IEFCachePolicyParser>(); | ||
var loggerMock = new Mock<IEFDebugLogger>(); | ||
var keyProviderLoggerMock = new Mock<ILogger<EFCacheKeyProvider>>(); | ||
var cacheKeyPrefixProviderMock = new Mock<IEFCacheKeyPrefixProvider>(); | ||
#if NET5_0 || NET6_0 || NET7_0 || NET8_0 | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
#endif | ||
|
||
// Act && Assert | ||
Assert.Throws<ArgumentNullException>(() => new EFCacheKeyProvider( | ||
cacheDependenciesProcessorMock.Object, | ||
cachePolicyParserMock.Object, | ||
loggerMock.Object, | ||
keyProviderLoggerMock.Object, | ||
// ReSharper disable once AssignNullToNotNullAttribute | ||
null, | ||
cacheKeyPrefixProviderMock.Object | ||
#if NET5_0 || NET6_0 || NET7_0 || NET8_0 | ||
, | ||
cacheSettingsMock.Object | ||
#endif | ||
)); | ||
} | ||
|
||
[Fact] | ||
public void EFCacheKeyProvider_ThrowsArgumentNullException_WhenCacheSettingsIsNull() | ||
{ | ||
// Arrange | ||
#if NET5_0 || NET6_0 || NET7_0 || NET8_0 | ||
var cacheDependenciesProcessorMock = new Mock<IEFCacheDependenciesProcessor>(); | ||
var cachePolicyParserMock = new Mock<IEFCachePolicyParser>(); | ||
var loggerMock = new Mock<IEFDebugLogger>(); | ||
var keyProviderLoggerMock = new Mock<ILogger<EFCacheKeyProvider>>(); | ||
var hashProviderMock = new Mock<IEFHashProvider>(); | ||
var cacheKeyPrefixProviderMock = new Mock<IEFCacheKeyPrefixProvider>(); | ||
|
||
// Act && Assert | ||
Assert.Throws<ArgumentNullException>(() => new EFCacheKeyProvider( | ||
cacheDependenciesProcessorMock.Object, | ||
cachePolicyParserMock.Object, | ||
loggerMock.Object, | ||
keyProviderLoggerMock.Object, | ||
hashProviderMock.Object, | ||
cacheKeyPrefixProviderMock.Object, | ||
// ReSharper disable once AssignNullToNotNullAttribute | ||
null | ||
)); | ||
#endif | ||
} | ||
|
||
[Fact] | ||
public void EFCacheKeyProvider_CreatesInstanceSuccessfully() | ||
{ | ||
// Arrange | ||
var cacheDependenciesProcessorMock = new Mock<IEFCacheDependenciesProcessor>(); | ||
var cachePolicyParserMock = new Mock<IEFCachePolicyParser>(); | ||
var loggerMock = new Mock<IEFDebugLogger>(); | ||
var keyProviderLoggerMock = new Mock<ILogger<EFCacheKeyProvider>>(); | ||
var hashProviderMock = new Mock<IEFHashProvider>(); | ||
var cacheKeyPrefixProviderMock = new Mock<IEFCacheKeyPrefixProvider>(); | ||
#if NET5_0 || NET6_0 || NET7_0 || NET8_0 | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
cacheSettingsMock.Setup(c => c.Value).Returns(new EFCoreSecondLevelCacheSettings()); | ||
#endif | ||
|
||
// Act | ||
var provider = new EFCacheKeyProvider( | ||
cacheDependenciesProcessorMock.Object, | ||
cachePolicyParserMock.Object, | ||
loggerMock.Object, | ||
keyProviderLoggerMock.Object, | ||
hashProviderMock.Object, | ||
cacheKeyPrefixProviderMock.Object | ||
#if NET5_0 || NET6_0 || NET7_0 || NET8_0 | ||
, | ||
cacheSettingsMock.Object | ||
#endif | ||
); | ||
|
||
// Assert | ||
Assert.NotNull(provider); | ||
} | ||
|
||
[Fact] | ||
[SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")] | ||
public void GetEFCacheKey_ThrowsArgumentNullException_WhenContextIsNull() | ||
{ | ||
// Arrange | ||
DbCommand command = null; | ||
DbContext context = null; | ||
EFCachePolicy cachePolicy = null; | ||
|
||
// Act | ||
void Act() => _cacheKeyProvider.GetEFCacheKey(command, context, cachePolicy); | ||
|
||
// Assert | ||
Assert.Throws<ArgumentNullException>("context", Act); | ||
} | ||
|
||
[Fact] | ||
[SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")] | ||
public void GetEFCacheKey_ThrowsArgumentNullException_WhenCommandIsNull() | ||
{ | ||
// Arrange | ||
DbCommand command = null; | ||
DbContext context = Mock.Of<DbContext>(); | ||
EFCachePolicy cachePolicy = null; | ||
|
||
// Act | ||
void Act() => _cacheKeyProvider.GetEFCacheKey(command, context, cachePolicy); | ||
|
||
// Assert | ||
Assert.Throws<ArgumentNullException>("command", Act); | ||
} | ||
|
||
[Fact] | ||
public void GetEFCacheKey_ThrowsArgumentNullException_WhenCachePolicyIsNull() | ||
{ | ||
// Arrange | ||
DbCommand command = Mock.Of<DbCommand>(); | ||
DbContext context = Mock.Of<DbContext>(); | ||
EFCachePolicy cachePolicy = null; | ||
|
||
// Act | ||
// ReSharper disable once AssignNullToNotNullAttribute | ||
void Act() => _cacheKeyProvider.GetEFCacheKey(command, context, cachePolicy); | ||
|
||
// Assert | ||
Assert.Throws<ArgumentNullException>("cachePolicy", Act); | ||
} | ||
|
||
[Fact] | ||
public void GetEFCacheKey_ReturnsExpectedCacheKey() | ||
{ | ||
// Arrange | ||
var context = Mock.Of<DbContext>(); | ||
var expected = new EFCacheKey(new SortedSet<string>()) | ||
{ | ||
KeyHash = "75BCD15", | ||
DbContext = context.GetType() | ||
}; | ||
|
||
var commandMock = new Mock<DbCommand>(); | ||
var cachePolicy = new EFCachePolicy().SaltKey("CacheSaltKey"); | ||
var dbParameterCollectionMock = new Mock<DbParameterCollection>(); | ||
var dbParameterMock = new Mock<DbParameter>(); | ||
var parameters = new List<DbParameter> | ||
{ | ||
dbParameterMock.Object, | ||
}; | ||
|
||
_hashProviderMock | ||
.Setup(x => x.ComputeHash(@"ConnectionString | ||
=Name=""Value"",Size=2147483647,Precision=255,Scale=255,Direction=Input,SaltKey | ||
=CacheSaltKey")) | ||
.Returns(123456789); | ||
|
||
_loggerMock.Setup(x => x.IsLoggerEnabled).Returns(true); | ||
|
||
commandMock | ||
.Protected() | ||
.SetupGet<DbParameterCollection>("DbParameterCollection") | ||
.Returns(dbParameterCollectionMock.Object); | ||
|
||
dbParameterCollectionMock | ||
.Setup(x => x.GetEnumerator()) | ||
.Returns(parameters.GetEnumerator()); | ||
|
||
_cacheDependenciesProcessorMock | ||
.Setup(x => x.GetCacheDependencies(commandMock.Object, context, cachePolicy)) | ||
.Returns(expected.CacheDependencies as SortedSet<string>); | ||
|
||
dbParameterMock.Setup(x => x.ParameterName).Returns("Name"); | ||
dbParameterMock.Setup(x => x.Value).Returns("Value"); | ||
dbParameterMock.Setup(x => x.Size).Returns(int.MaxValue); | ||
dbParameterMock.Setup(x => x.Precision).Returns(byte.MaxValue); | ||
dbParameterMock.Setup(x => x.Scale).Returns(byte.MaxValue); | ||
dbParameterMock.Setup(x => x.Direction).Returns(ParameterDirection.Input); | ||
|
||
// Act | ||
var actual = _cacheKeyProvider.GetEFCacheKey(commandMock.Object, context, cachePolicy); | ||
|
||
// Assert | ||
Assert.Equal(expected, actual); | ||
} | ||
|
||
[Fact] | ||
public void GetEFCacheKey_ReturnsExpectedCacheKeyWithPrefix() | ||
{ | ||
// Arrange | ||
var context = Mock.Of<DbContext>(); | ||
var expected = new EFCacheKey(new SortedSet<string>()) | ||
{ | ||
KeyHash = "CacheKeyPrefix75BCD15", | ||
DbContext = context.GetType() | ||
}; | ||
|
||
var commandMock = new Mock<DbCommand>(); | ||
var cachePolicy = new EFCachePolicy().SaltKey("CacheSaltKey"); | ||
var dbParameterCollectionMock = new Mock<DbParameterCollection>(); | ||
var dbParameterMock = new Mock<DbParameter>(); | ||
var parameters = new List<DbParameter> | ||
{ | ||
dbParameterMock.Object, | ||
}; | ||
|
||
_cacheKeyPrefixProviderMock | ||
.Setup(x => x.GetCacheKeyPrefix()) | ||
.Returns("CacheKeyPrefix"); | ||
|
||
_hashProviderMock | ||
.Setup(x => x.ComputeHash(@"ConnectionString | ||
=Name=""Value"",Size=2147483647,Precision=255,Scale=255,Direction=Input,SaltKey | ||
=CacheSaltKey")) | ||
.Returns(123456789); | ||
|
||
_loggerMock.Setup(x => x.IsLoggerEnabled).Returns(true); | ||
|
||
commandMock | ||
.Protected() | ||
.SetupGet<DbParameterCollection>("DbParameterCollection") | ||
.Returns(dbParameterCollectionMock.Object); | ||
|
||
dbParameterCollectionMock | ||
.Setup(x => x.GetEnumerator()) | ||
.Returns(parameters.GetEnumerator()); | ||
|
||
_cacheDependenciesProcessorMock | ||
.Setup(x => x.GetCacheDependencies(commandMock.Object, context, cachePolicy)) | ||
.Returns(expected.CacheDependencies as SortedSet<string>); | ||
|
||
dbParameterMock.Setup(x => x.ParameterName).Returns("Name"); | ||
dbParameterMock.Setup(x => x.Value).Returns("Value"); | ||
dbParameterMock.Setup(x => x.Size).Returns(int.MaxValue); | ||
dbParameterMock.Setup(x => x.Precision).Returns(byte.MaxValue); | ||
dbParameterMock.Setup(x => x.Scale).Returns(byte.MaxValue); | ||
dbParameterMock.Setup(x => x.Direction).Returns(ParameterDirection.Input); | ||
|
||
// Act | ||
var actual = _cacheKeyProvider.GetEFCacheKey(commandMock.Object, context, cachePolicy); | ||
|
||
// Assert | ||
Assert.Equal(expected, actual); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
using Microsoft.EntityFrameworkCore; | ||
using Moq; | ||
|
||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
// ReSharper disable once InconsistentNaming | ||
public class EFCacheKeyTests | ||
{ | ||
[Fact] | ||
public void Equals_ReturnsTrue_WhenKeyHashAndDbContextAreEqual() | ||
{ | ||
// Arrange | ||
var cacheKey1 = new EFCacheKey(new HashSet<string> { "Entity1" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
var cacheKey2 = new EFCacheKey(new HashSet<string> { "Entity2" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
// Act | ||
var actual = cacheKey1.Equals(cacheKey2); | ||
|
||
// Assert | ||
Assert.True(actual); | ||
} | ||
|
||
[Fact] | ||
public void Equals_ReturnsFalse_WhenObjIsNotEFCacheKey() | ||
{ | ||
// Arrange | ||
var cacheKey1 = new EFCacheKey(new HashSet<string> { "Entity1" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
var obj = new object(); | ||
|
||
// Act | ||
var actual = cacheKey1.Equals(obj); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void Equals_ReturnsFalse_WhenKeyHashIsDifferent() | ||
{ | ||
// Arrange | ||
var cacheKey1 = new EFCacheKey(new HashSet<string> { "Entity1" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
var cacheKey2 = new EFCacheKey(new HashSet<string> { "Entity2" }) | ||
{ | ||
KeyHash = "hash2", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
// Act | ||
var actual = cacheKey1.Equals(cacheKey2); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void Equals_ReturnsFalse_WhenDbContextIsDifferent() | ||
{ | ||
// Arrange | ||
var cacheKey1 = new EFCacheKey(new HashSet<string> { "Entity1" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
var cacheKey2 = new EFCacheKey(new HashSet<string> { "Entity2" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = Mock.Of<DbContext>().GetType() | ||
}; | ||
|
||
// Act | ||
var actual = cacheKey1.Equals(cacheKey2); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void GetHashCode_ReturnsSameHashCode_ForEqualObjects() | ||
{ | ||
// Arrange | ||
var cacheKey1 = new EFCacheKey(new HashSet<string> { "Entity1" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
var cacheKey2 = new EFCacheKey(new HashSet<string> { "Entity2" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
// Act | ||
var hashCode1 = cacheKey1.GetHashCode(); | ||
var hashCode2 = cacheKey2.GetHashCode(); | ||
|
||
// Assert | ||
Assert.Equal(hashCode1, hashCode2); | ||
} | ||
|
||
[Fact] | ||
public void GetHashCode_ReturnsDifferentHashCode_ForDifferentObjects() | ||
{ | ||
// Arrange | ||
var cacheKey1 = new EFCacheKey(new HashSet<string> { "Entity1" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
var cacheKey2 = new EFCacheKey(new HashSet<string> { "Entity2" }) | ||
{ | ||
KeyHash = "hash2", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
// Act | ||
var hashCode1 = cacheKey1.GetHashCode(); | ||
var hashCode2 = cacheKey2.GetHashCode(); | ||
|
||
// Assert | ||
Assert.NotEqual(hashCode1, hashCode2); | ||
} | ||
|
||
[Fact] | ||
public void ToString_ReturnsExpectedFormat() | ||
{ | ||
// Arrange | ||
var cacheKey = new EFCacheKey(new HashSet<string> { "Entity1", "Entity2" }) | ||
{ | ||
KeyHash = "hash1", | ||
DbContext = typeof(DbContext) | ||
}; | ||
|
||
// Act | ||
var actual = cacheKey.ToString(); | ||
|
||
// Assert | ||
Assert.Equal("KeyHash: hash1, DbContext: DbContext, CacheDependencies: Entity1, Entity2.", actual); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
using Microsoft.Extensions.Options; | ||
using Moq; | ||
|
||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
// ReSharper disable once InconsistentNaming | ||
public class EFCacheServiceCheckTests | ||
{ | ||
private readonly Mock<IEFCacheServiceProvider> _cacheServiceProviderMock; | ||
private readonly EFCoreSecondLevelCacheSettings _cacheSettings; | ||
private readonly IEFCacheServiceCheck _serviceCheck; | ||
|
||
public EFCacheServiceCheckTests() | ||
{ | ||
var cacheOptionsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
|
||
_cacheServiceProviderMock = new Mock<IEFCacheServiceProvider>(); | ||
_cacheSettings = new EFCoreSecondLevelCacheSettings(); | ||
|
||
cacheOptionsMock.Setup(c => c.Value).Returns(_cacheSettings); | ||
|
||
_serviceCheck = new EFCacheServiceCheck(cacheOptionsMock.Object, _cacheServiceProviderMock.Object); | ||
} | ||
|
||
[Fact] | ||
public void EFCacheServiceCheck_ThrowsArgumentNullException_WhenCacheSettingsIsNull() | ||
{ | ||
// Arrange | ||
var cacheServiceProviderMock = new Mock<IEFCacheServiceProvider>(); | ||
|
||
// Act && Assert | ||
// ReSharper disable once AssignNullToNotNullAttribute | ||
Assert.Throws<ArgumentNullException>(() => new EFCacheServiceCheck(null, cacheServiceProviderMock.Object)); | ||
} | ||
|
||
[Fact] | ||
public void EFCacheServiceCheck_CreatesInstanceSuccessfully() | ||
{ | ||
// Arrange | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
|
||
cacheSettingsMock.Setup(c => c.Value).Returns(new EFCoreSecondLevelCacheSettings()); | ||
|
||
var cacheServiceProviderMock = new Mock<IEFCacheServiceProvider>(); | ||
|
||
// Act | ||
var serviceCheck = new EFCacheServiceCheck(cacheSettingsMock.Object, cacheServiceProviderMock.Object); | ||
|
||
// Assert | ||
Assert.NotNull(serviceCheck); | ||
} | ||
|
||
[Fact] | ||
public void EFCacheServiceCheck_ShouldNotThrowArgumentNullException_WhenCacheServiceProviderIsNull() | ||
{ | ||
// Arrange | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
|
||
cacheSettingsMock.Setup(c => c.Value).Returns(new EFCoreSecondLevelCacheSettings()); | ||
|
||
// ReSharper disable once AssignNullToNotNullAttribute | ||
// ReSharper disable once ObjectCreationAsStatement | ||
void Act() => new EFCacheServiceCheck(cacheSettingsMock.Object, null); | ||
|
||
// Act | ||
var actual = Record.Exception(Act); | ||
|
||
// Assert | ||
Assert.Null(actual); | ||
} | ||
|
||
[Fact] | ||
public void IsCacheServiceAvailable_ReturnsFalse_WhenIsCachingInterceptorEnabledIsFalse() | ||
{ | ||
// Arrange | ||
_cacheSettings.IsCachingInterceptorEnabled = false; | ||
|
||
// Act | ||
var result = _serviceCheck.IsCacheServiceAvailable(); | ||
|
||
// Assert | ||
Assert.False(result); | ||
} | ||
|
||
[Fact] | ||
public void IsCacheServiceAvailable_ReturnsTrue_WhenUseDbCallsIfCachingProviderIsDownIsFalse() | ||
{ | ||
// Arrange | ||
_cacheSettings.IsCachingInterceptorEnabled = true; | ||
_cacheSettings.UseDbCallsIfCachingProviderIsDown = false; | ||
|
||
// Act | ||
var result = _serviceCheck.IsCacheServiceAvailable(); | ||
|
||
// Assert | ||
Assert.True(result); | ||
} | ||
|
||
[Fact] | ||
public void | ||
IsCacheServiceAvailable_ReturnsTrue_WhenUseDbCallsIfCachingProviderIsDownIsTrue_And_CacheServerIsAvailable() | ||
{ | ||
// Arrange | ||
_cacheSettings.IsCachingInterceptorEnabled = true; | ||
_cacheSettings.UseDbCallsIfCachingProviderIsDown = true; | ||
|
||
_cacheServiceProviderMock | ||
.Setup(c => c.GetValue(It.IsAny<EFCacheKey>(), It.IsAny<EFCachePolicy>())) | ||
.Returns(new EFCachedData()); | ||
|
||
// Act | ||
var result = _serviceCheck.IsCacheServiceAvailable(); | ||
|
||
// Assert | ||
Assert.True(result); | ||
} | ||
|
||
[Fact] | ||
public void | ||
IsCacheServiceAvailable_ThrowsInvalidOperationException_WhenUseDbCallsIfCachingProviderIsDownIsTrue_And_CacheServerIsNotAvailable() | ||
{ | ||
// Arrange | ||
_cacheSettings.IsCachingInterceptorEnabled = true; | ||
_cacheSettings.UseDbCallsIfCachingProviderIsDown = true; | ||
|
||
_cacheServiceProviderMock | ||
.Setup(c => c.GetValue(It.IsAny<EFCacheKey>(), It.IsAny<EFCachePolicy>())) | ||
.Throws<InvalidOperationException>(); | ||
|
||
// Act | ||
void Act() => _serviceCheck.IsCacheServiceAvailable(); | ||
|
||
// Assert | ||
Assert.Throws<InvalidOperationException>(Act); | ||
} | ||
|
||
[Fact] | ||
public void IsCacheServiceAvailable_ReturnsTrue_WhenNotEnoughTimeHasPassedSinceTheLastCheck() | ||
{ | ||
// Arrange | ||
_cacheSettings.IsCachingInterceptorEnabled = true; | ||
_cacheSettings.UseDbCallsIfCachingProviderIsDown = true; | ||
_cacheSettings.NextCacheServerAvailabilityCheck = TimeSpan.MaxValue; | ||
|
||
_cacheServiceProviderMock | ||
.Setup(c => c.GetValue(It.IsAny<EFCacheKey>(), It.IsAny<EFCachePolicy>())) | ||
.Returns(new EFCachedData()); | ||
|
||
_serviceCheck.IsCacheServiceAvailable(); | ||
|
||
// Act | ||
var result = _serviceCheck.IsCacheServiceAvailable(); | ||
|
||
// Assert | ||
Assert.True(result); | ||
} | ||
} |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
using Moq; | ||
|
||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
// ReSharper disable once InconsistentNaming | ||
public class EFDebugLoggerTests | ||
{ | ||
private readonly Mock<Action<EFCacheableLogEvent>> _cacheableEventMock; | ||
private readonly Mock<Action<EFCacheInvalidationInfo>> _cacheInvalidationEventMock; | ||
private readonly Mock<IServiceProvider> _serviceProviderMock; | ||
private readonly IEFDebugLogger _debugLogger; | ||
|
||
public EFDebugLoggerTests() | ||
{ | ||
_cacheableEventMock = new Mock<Action<EFCacheableLogEvent>>(); | ||
_cacheInvalidationEventMock = new Mock<Action<EFCacheInvalidationInfo>>(); | ||
_serviceProviderMock = new Mock<IServiceProvider>(); | ||
|
||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
var loggerMock = new Mock<ILogger<EFDebugLogger>>(); | ||
var cacheSettings = new EFCoreSecondLevelCacheSettings | ||
{ | ||
EnableLogging = true, | ||
CacheableEvent = _cacheableEventMock.Object, | ||
CacheInvalidationEvent = _cacheInvalidationEventMock.Object | ||
}; | ||
|
||
cacheSettingsMock.Setup(c => c.Value).Returns(cacheSettings); | ||
loggerMock.Setup(l => l.IsEnabled(LogLevel.Debug)).Returns(true); | ||
|
||
_debugLogger = new EFDebugLogger( | ||
cacheSettingsMock.Object, | ||
loggerMock.Object, | ||
_serviceProviderMock.Object); | ||
} | ||
|
||
[Fact] | ||
public void EFDebugLogger_ThrowsArgumentNullException_WhenCacheSettingsIsNull() | ||
{ | ||
// Arrange | ||
var loggerMock = new Mock<ILogger<EFDebugLogger>>(); | ||
var serviceProviderMock = new Mock<IServiceProvider>(); | ||
|
||
Assert.Throws<ArgumentNullException>(() => | ||
new EFDebugLogger(null!, loggerMock.Object, serviceProviderMock.Object)); | ||
} | ||
|
||
[Fact] | ||
public void EFDebugLogger_ThrowsArgumentNullException_WhenLoggerIsNull() | ||
{ | ||
// Arrange | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
var serviceProviderMock = new Mock<IServiceProvider>(); | ||
|
||
// Act && Assert | ||
Assert.Throws<ArgumentNullException>(() => | ||
new EFDebugLogger(cacheSettingsMock.Object, null!, serviceProviderMock.Object)); | ||
} | ||
|
||
[Fact] | ||
public void EFDebugLogger_EnablesLogging_WhenCacheSettingsEnableLoggingIsTrue() | ||
{ | ||
// Arrange | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
var loggerMock = new Mock<ILogger<EFDebugLogger>>(); | ||
var serviceProviderMock = new Mock<IServiceProvider>(); | ||
|
||
cacheSettingsMock.Setup(c => c.Value).Returns(new EFCoreSecondLevelCacheSettings { EnableLogging = true }); | ||
loggerMock.Setup(l => l.IsEnabled(LogLevel.Debug)).Returns(true); | ||
|
||
// Act | ||
var logger = new EFDebugLogger(cacheSettingsMock.Object, loggerMock.Object, serviceProviderMock.Object); | ||
|
||
// Assert | ||
Assert.True(logger.IsLoggerEnabled); | ||
} | ||
|
||
[Fact] | ||
public void EFDebugLogger_DisablesLogging_WhenCacheSettingsEnableLoggingIsFalse() | ||
{ | ||
// Arrange | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
var loggerMock = new Mock<ILogger<EFDebugLogger>>(); | ||
var serviceProviderMock = new Mock<IServiceProvider>(); | ||
|
||
cacheSettingsMock.Setup(c => c.Value).Returns(new EFCoreSecondLevelCacheSettings { EnableLogging = false }); | ||
|
||
// Act | ||
var logger = new EFDebugLogger(cacheSettingsMock.Object, loggerMock.Object, serviceProviderMock.Object); | ||
|
||
// Assert | ||
Assert.False(logger.IsLoggerEnabled); | ||
} | ||
|
||
[Fact] | ||
public void NotifyCacheableEvent_InvokesCacheableEvent_WhenLoggerIsEnabled() | ||
{ | ||
// Arrange && Act | ||
_debugLogger.NotifyCacheableEvent(CacheableLogEventId.CachingSystemStarted, "TestMessage", "TestCommand"); | ||
|
||
// Assert | ||
_cacheableEventMock.Verify(e => e.Invoke(It.Is<EFCacheableLogEvent>( | ||
x => | ||
x.EventId == CacheableLogEventId.CachingSystemStarted | ||
&& x.Message == "TestMessage" | ||
&& x.CommandText == "TestCommand" | ||
&& x.ServiceProvider == _serviceProviderMock.Object)), | ||
Times.Once); | ||
} | ||
|
||
[Fact] | ||
public void NotifyCacheableEvent_DoesNotInvokeCacheableEvent_WhenLoggerIsDisabled() | ||
{ | ||
// Arrange | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
var loggerMock = new Mock<ILogger<EFDebugLogger>>(); | ||
var serviceProviderMock = new Mock<IServiceProvider>(); | ||
var cacheableEventMock = new Mock<Action<EFCacheableLogEvent>>(); | ||
|
||
cacheSettingsMock.Setup(c => c.Value).Returns(new EFCoreSecondLevelCacheSettings { EnableLogging = false }); | ||
cacheSettingsMock.Object.Value.CacheableEvent = cacheableEventMock.Object; | ||
|
||
var logger = new EFDebugLogger(cacheSettingsMock.Object, loggerMock.Object, serviceProviderMock.Object); | ||
|
||
// Act | ||
logger.NotifyCacheableEvent(CacheableLogEventId.CachingSystemStarted, "TestMessage", "TestCommand"); | ||
|
||
// Assert | ||
cacheableEventMock.Verify(e => e.Invoke(It.IsAny<EFCacheableLogEvent>()), Times.Never); | ||
} | ||
|
||
[Fact] | ||
public void NotifyCacheableEvent_DoesNotInvokeCacheableEvent_WhenCacheableEventIsNull() | ||
{ | ||
// Arrange | ||
var cacheSettingsMock = new Mock<IOptions<EFCoreSecondLevelCacheSettings>>(); | ||
var serviceProviderMock = new Mock<IServiceProvider>(); | ||
var loggerMock = new Mock<ILogger<EFDebugLogger>>(); | ||
var cacheableEventMock = new Mock<Action<EFCacheableLogEvent>>(); | ||
|
||
cacheSettingsMock.Setup(c => c.Value).Returns(new EFCoreSecondLevelCacheSettings { EnableLogging = true }); | ||
loggerMock.Setup(l => l.IsEnabled(LogLevel.Debug)).Returns(true); | ||
|
||
var logger = new EFDebugLogger(cacheSettingsMock.Object, loggerMock.Object, serviceProviderMock.Object); | ||
|
||
// Act | ||
logger.NotifyCacheableEvent(CacheableLogEventId.CachingSystemStarted, "TestMessage", "TestCommand"); | ||
|
||
// Assert | ||
cacheableEventMock.Verify(e => e.Invoke(It.IsAny<EFCacheableLogEvent>()), Times.Never); | ||
} | ||
|
||
[Fact] | ||
public void NotifyCacheInvalidation_InvokesEFCacheInvalidationInfo() | ||
{ | ||
// Arrange | ||
var cacheDependencies = new HashSet<string>(); | ||
|
||
// Act | ||
_debugLogger.NotifyCacheInvalidation(true, cacheDependencies); | ||
|
||
// Assert | ||
_cacheInvalidationEventMock.Verify(e => e.Invoke(It.Is<EFCacheInvalidationInfo>( | ||
x => | ||
x.CacheDependencies == cacheDependencies | ||
Check warning Code scanning / CodeQL Reference equality test on System.Object Warning
Reference equality for System.Object comparisons (
this Error loading related location Loading |
||
&& x.ClearAllCachedEntries == true | ||
Check notice Code scanning / CodeQL Unnecessarily complex Boolean expression Note
The expression 'A == true' can be simplified to 'A'.
|
||
&& x.ServiceProvider == _serviceProviderMock.Object)), | ||
Check warning Code scanning / CodeQL Reference equality test on System.Object Warning
Reference equality for System.Object comparisons (
this Error loading related location Loading |
||
Times.Once); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.DependencyInjection.Extensions; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
// ReSharper disable once InconsistentNaming | ||
public class EFServiceCollectionExtensionsTests | ||
{ | ||
[Fact] | ||
public void AddEFSecondLevelCache_ThrowsArgumentNullException_WhenOptionsIsNull() | ||
{ | ||
// Arrange | ||
var services = new ServiceCollection(); | ||
|
||
// Act && Assert | ||
Assert.Throws<ArgumentNullException>(() => services.AddEFSecondLevelCache(null!)); | ||
} | ||
|
||
[Fact] | ||
public void AddEFSecondLevelCache_RegistersRequiredServices() | ||
{ | ||
// Arrange | ||
var services = new ServiceCollection(); | ||
|
||
// Act | ||
services.TryAddSingleton(typeof(ILogger<>), typeof(Logger<>)); | ||
services.AddEFSecondLevelCache(_ => { }); | ||
|
||
// Assert | ||
var serviceProvider = services.BuildServiceProvider(); | ||
|
||
Assert.NotNull(serviceProvider.GetService<IEFDebugLogger>()); | ||
Assert.NotNull(serviceProvider.GetService<IEFCacheServiceCheck>()); | ||
Assert.NotNull(serviceProvider.GetService<IEFCacheKeyPrefixProvider>()); | ||
Assert.NotNull(serviceProvider.GetService<IEFCacheKeyProvider>()); | ||
Assert.NotNull(serviceProvider.GetService<IEFCachePolicyParser>()); | ||
Assert.NotNull(serviceProvider.GetService<IEFSqlCommandsProcessor>()); | ||
Assert.NotNull(serviceProvider.GetService<IEFCacheDependenciesProcessor>()); | ||
Assert.NotNull(serviceProvider.GetService<ILockProvider>()); | ||
Assert.NotNull(serviceProvider.GetService<IMemoryCacheChangeTokenProvider>()); | ||
Assert.NotNull(serviceProvider.GetService<IDbCommandInterceptorProcessor>()); | ||
Assert.NotNull(serviceProvider.GetService<SecondLevelCacheInterceptor>()); | ||
} | ||
|
||
[Fact] | ||
public void AddEFSecondLevelCache_RegistersDefaultHashProvider_WhenHashProviderIsNull() | ||
{ | ||
// Arrange | ||
var services = new ServiceCollection(); | ||
|
||
// Act | ||
services.AddEFSecondLevelCache(options => { options.Settings.HashProvider = null; }); | ||
|
||
// Assert | ||
var serviceProvider = services.BuildServiceProvider(); | ||
|
||
Assert.IsType<XxHash64Unsafe>(serviceProvider.GetService<IEFHashProvider>()); | ||
} | ||
|
||
[Fact] | ||
public void AddEFSecondLevelCache_RegistersCustomHashProvider_WhenHashProviderIsNotNull() | ||
{ | ||
// Arrange | ||
var services = new ServiceCollection(); | ||
|
||
// Act | ||
services.AddEFSecondLevelCache(options => { options.Settings.HashProvider = typeof(CustomHashProvider); }); | ||
|
||
// Assert | ||
var serviceProvider = services.BuildServiceProvider(); | ||
|
||
Assert.IsType<CustomHashProvider>(serviceProvider.GetService<IEFHashProvider>()); | ||
} | ||
|
||
[Fact] | ||
public void AddEFSecondLevelCache_RegistersDefaultCacheProvider_WhenCacheProviderIsNull() | ||
{ | ||
// Arrange | ||
var services = new ServiceCollection(); | ||
|
||
// Act | ||
services.AddEFSecondLevelCache(options => { options.Settings.CacheProvider = null; }); | ||
|
||
// Assert | ||
var serviceProvider = services.BuildServiceProvider(); | ||
|
||
Assert.IsType<EFMemoryCacheServiceProvider>(serviceProvider.GetService<IEFCacheServiceProvider>()); | ||
} | ||
|
||
[Fact] | ||
public void AddEFSecondLevelCache_RegistersCustomCacheProvider_WhenCacheProviderIsNotNull() | ||
{ | ||
// Arrange | ||
var services = new ServiceCollection(); | ||
|
||
// Act | ||
services.AddEFSecondLevelCache(options => { options.Settings.CacheProvider = typeof(CustomCacheProvider); }); | ||
|
||
// Assert | ||
var serviceProvider = services.BuildServiceProvider(); | ||
|
||
Assert.IsType<CustomCacheProvider>(serviceProvider.GetService<IEFCacheServiceProvider>()); | ||
} | ||
|
||
private class Logger<TCategoryName> : ILogger<TCategoryName> | ||
{ | ||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, | ||
Func<TState, Exception, string> formatter) => throw new NotImplementedException(); | ||
|
||
public bool IsEnabled(LogLevel logLevel) => throw new NotImplementedException(); | ||
|
||
public IDisposable BeginScope<TState>(TState state) where TState : notnull => | ||
throw new NotImplementedException(); | ||
} | ||
|
||
private class CustomHashProvider : IEFHashProvider | ||
{ | ||
public ulong ComputeHash(string data) => throw new NotImplementedException(); | ||
|
||
public ulong ComputeHash(byte[] data) => throw new NotImplementedException(); | ||
|
||
public ulong ComputeHash(byte[] data, int offset, int len, uint seed) => throw new NotImplementedException(); | ||
} | ||
|
||
private class CustomCacheProvider : IEFCacheServiceProvider | ||
{ | ||
public void ClearAllCachedEntries() => throw new NotImplementedException(); | ||
|
||
public EFCachedData GetValue(EFCacheKey cacheKey, EFCachePolicy cachePolicy) => | ||
throw new NotImplementedException(); | ||
|
||
public void InsertValue(EFCacheKey cacheKey, EFCachedData value, EFCachePolicy cachePolicy) => | ||
throw new NotImplementedException(); | ||
|
||
public void InvalidateCacheDependencies(EFCacheKey cacheKey) => throw new NotImplementedException(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
using AsyncKeyedLock; | ||
|
||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
public class LockProviderTests | ||
{ | ||
[Fact] | ||
public void Lock_ReturnsNonNullReleaser() | ||
{ | ||
// Arrange | ||
var lockProvider = new LockProvider(); | ||
|
||
// Act | ||
var releaser = lockProvider.Lock(); | ||
|
||
// Assert | ||
Assert.IsType<AsyncNonKeyedLockReleaser>(releaser); | ||
} | ||
|
||
[Fact] | ||
public async Task LockAsync_ReturnsNonNullReleaser() | ||
{ | ||
// Arrange | ||
var lockProvider = new LockProvider(); | ||
|
||
// Act | ||
var releaser = await lockProvider.LockAsync(); | ||
|
||
// Assert | ||
Assert.IsType<AsyncNonKeyedLockReleaser>(releaser); | ||
} | ||
|
||
[Fact] | ||
public void Lock_CanBeDisposed() | ||
{ | ||
// Arrange | ||
var lockProvider = new LockProvider(); | ||
var releaser = lockProvider.Lock(); | ||
|
||
// Act | ||
releaser.Dispose(); | ||
|
||
// Assert | ||
Assert.True(true); // If no exception is thrown, the test passes | ||
} | ||
|
||
[Fact] | ||
public async Task LockAsync_CanBeDisposed() | ||
{ | ||
// Arrange | ||
var lockProvider = new LockProvider(); | ||
var releaser = await lockProvider.LockAsync(); | ||
|
||
// Act | ||
releaser.Dispose(); | ||
|
||
// Assert | ||
Assert.True(true); // If no exception is thrown, the test passes | ||
} | ||
|
||
[Fact] | ||
public void Dispose_DisposesLockProvider() | ||
{ | ||
// Arrange | ||
var lockProvider = new LockProvider(); | ||
|
||
// Act | ||
lockProvider.Dispose(); | ||
|
||
// Assert | ||
Assert.True(true); // If no exception is thrown, the test passes | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
public class StringExtensionsTests | ||
{ | ||
[Fact] | ||
public void EndsWith_ReturnsFalse_WhenValueIsNull() | ||
{ | ||
// Arrange | ||
var collection = new List<string> { "testValue", "anotherValue" }; | ||
|
||
// Act | ||
var actual = collection.EndsWith(null, StringComparison.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void EndsWith_ReturnsTrue_WhenCollectionContainsItemEndingWithValue() | ||
{ | ||
// Arrange | ||
var collection = new List<string> { "testValue", "anotherValue" }; | ||
|
||
// Act | ||
var actual = collection.EndsWith("Value", StringComparison.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.True(actual); | ||
} | ||
|
||
[Fact] | ||
public void EndsWith_ReturnsFalse_WhenCollectionDoesNotContainItemEndingWithValue() | ||
{ | ||
// Arrange | ||
var collection = new List<string> { "testValue", "anotherValue" }; | ||
|
||
// Act | ||
var actual = collection.EndsWith("NotExist", StringComparison.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void StartsWith_ReturnsFalse_WhenValueIsNull() | ||
{ | ||
// Arrange | ||
var collection = new List<string> { "ValueTest", "ValueAnother" }; | ||
|
||
// Act | ||
var actual = collection.StartsWith(null, StringComparison.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void StartsWith_ReturnsTrue_WhenCollectionContainsItemStartingWithValue() | ||
{ | ||
// Arrange | ||
var collection = new List<string> { "ValueTest", "ValueAnother" }; | ||
|
||
// Act | ||
var actual = collection.StartsWith("Value", StringComparison.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.True(actual); | ||
} | ||
|
||
[Fact] | ||
public void StartsWith_ReturnsFalse_WhenCollectionDoesNotContainItemStartingWithValue() | ||
{ | ||
// Arrange | ||
var collection = new List<string> { "ValueTest", "ValueAnother" }; | ||
|
||
// Act | ||
var actual = collection.StartsWith("NotExist", StringComparison.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void ContainsEvery_ReturnsFalse_WhenCollectionIsNull() | ||
{ | ||
// Arrange | ||
var source = new List<string> { "item1", "item2", "item3" }; | ||
|
||
// Act | ||
var actual = source.ContainsEvery(null, StringComparer.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void ContainsEvery_ReturnsTrue_WhenSourceContainsEveryItemInCollection() | ||
{ | ||
// Arrange | ||
var source = new List<string> { "item1", "item2", "item3" }; | ||
var collection = new List<string> { "item1", "item2", "item3" }; | ||
|
||
// Act | ||
var actual = source.ContainsEvery(collection, StringComparer.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.True(actual); | ||
} | ||
|
||
[Fact] | ||
public void ContainsEvery_ReturnsFalse_WhenSourceDoesNotContainEveryItemInCollection() | ||
{ | ||
// Arrange | ||
var source = new List<string> { "item1", "item2" }; | ||
var collection = new List<string> { "item1", "item2", "item3" }; | ||
|
||
// Act | ||
var actual = source.ContainsEvery(collection, StringComparer.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void ContainsOnly_ReturnsFalse_WhenCollectionIsNull() | ||
{ | ||
// Arrange | ||
var source = new List<string> { "item1", "item2" }; | ||
|
||
// Act | ||
var actual = source.ContainsOnly(null, StringComparer.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
|
||
[Fact] | ||
public void ContainsOnly_ReturnsTrue_WhenSourceContainsOnlyItemsInCollection() | ||
{ | ||
// Arrange | ||
var source = new List<string> { "item1", "item2" }; | ||
var collection = new List<string> { "item1", "item2", "item3" }; | ||
|
||
// Act | ||
var actual = source.ContainsOnly(collection, StringComparer.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.True(actual); | ||
} | ||
|
||
[Fact] | ||
public void ContainsOnly_ReturnsFalse_WhenSourceContainsItemsNotInCollection() | ||
{ | ||
// Arrange | ||
var source = new List<string> { "item1", "item4" }; | ||
var collection = new List<string> { "item1", "item2", "item3" }; | ||
|
||
// Act | ||
var actual = source.ContainsOnly(collection, StringComparer.OrdinalIgnoreCase); | ||
|
||
// Assert | ||
Assert.False(actual); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
public class TableEntityInfoTests | ||
{ | ||
[Fact] | ||
public void ToString_ReturnsExpectedFormat_WhenClrTypeAndTableNameAreSet() | ||
{ | ||
// Arrange | ||
var entityInfo = new TableEntityInfo | ||
{ | ||
ClrType = typeof(string), | ||
TableName = "TestTable" | ||
}; | ||
|
||
// Act | ||
var actual = entityInfo.ToString(); | ||
|
||
// Assert | ||
Assert.Equal("System.String::TestTable", actual); | ||
} | ||
|
||
[Fact] | ||
public void ToString_ReturnsExpectedFormat_WhenClrTypeIsNull() | ||
{ | ||
// Arrange | ||
var entityInfo = new TableEntityInfo | ||
{ | ||
ClrType = null!, | ||
TableName = "TestTable" | ||
}; | ||
|
||
// Act | ||
var actual = entityInfo.ToString(); | ||
|
||
// Assert | ||
Assert.Equal("::TestTable", actual); | ||
} | ||
|
||
[Fact] | ||
public void ToString_ReturnsExpectedFormat_WhenTableNameIsNull() | ||
{ | ||
// Arrange | ||
var entityInfo = new TableEntityInfo | ||
{ | ||
ClrType = typeof(string), | ||
TableName = null! | ||
}; | ||
|
||
// Act | ||
var actual = entityInfo.ToString(); | ||
|
||
// Assert | ||
Assert.Equal("System.String::", actual); | ||
} | ||
|
||
[Fact] | ||
public void ToString_ReturnsExpectedFormat_WhenBothClrTypeAndTableNameAreNull() | ||
{ | ||
// Arrange | ||
var entityInfo = new TableEntityInfo | ||
{ | ||
ClrType = null!, | ||
TableName = null! | ||
}; | ||
|
||
// Act | ||
var actual = entityInfo.ToString(); | ||
|
||
// Assert | ||
Assert.Equal("::", actual); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
namespace EFCoreSecondLevelCacheInterceptor.UnitTests; | ||
|
||
public class XxHash64UnsafeTests | ||
{ | ||
[Fact] | ||
public void ComputeHash_ThrowsArgumentNullException_WhenStringDataIsNull() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
|
||
// Act && Assert | ||
Assert.Throws<ArgumentNullException>(() => hashProvider.ComputeHash(((string)null)!)); | ||
Check warning Code scanning / CodeQL Useless upcast Warning
There is no need to upcast from
null Error loading related location Loading String Error loading related location Loading |
||
} | ||
|
||
[Fact] | ||
public void ComputeHash_ThrowsArgumentNullException_WhenByteArrayDataIsNull() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
|
||
// Act && Assert | ||
Assert.Throws<ArgumentNullException>(() => hashProvider.ComputeHash(((byte[])null)!)); | ||
Check warning Code scanning / CodeQL Useless upcast Warning
There is no need to upcast from
null Error loading related location Loading Byte[] Error loading related location Loading |
||
} | ||
|
||
[Fact] | ||
public void ComputeHash_ThrowsArgumentNullException_WhenByteArrayDataWithOffsetIsNull() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
|
||
// Act && Assert | ||
Assert.Throws<ArgumentNullException>(() => hashProvider.ComputeHash(null!, 0, 0, 0)); | ||
} | ||
|
||
[Fact] | ||
public void ComputeHash_ReturnsSameHash_ForSameStringData() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
var data = "test"; | ||
|
||
// Act | ||
var hash1 = hashProvider.ComputeHash(data); | ||
var hash2 = hashProvider.ComputeHash(data); | ||
|
||
// Act && Assert | ||
Assert.Equal(hash1, hash2); | ||
} | ||
|
||
[Fact] | ||
public void ComputeHash_ReturnsSameHash_ForSameByteArrayData() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
var data = "test"u8.ToArray(); | ||
|
||
// Act | ||
var hash1 = hashProvider.ComputeHash(data); | ||
var hash2 = hashProvider.ComputeHash(data); | ||
|
||
// Act && Assert | ||
Assert.Equal(hash1, hash2); | ||
} | ||
|
||
[Fact] | ||
public void ComputeHash_ReturnsSameHash_ForSameByteArrayDataWithOffset() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
var data = "test"u8.ToArray(); | ||
|
||
// Act | ||
var hash1 = hashProvider.ComputeHash(data, 0, data.Length, 0); | ||
var hash2 = hashProvider.ComputeHash(data, 0, data.Length, 0); | ||
|
||
// Act && Assert | ||
Assert.Equal(hash1, hash2); | ||
} | ||
|
||
[Fact] | ||
public void ComputeHash_ReturnsDifferentHash_ForDifferentStringData() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
|
||
// Act | ||
var hash1 = hashProvider.ComputeHash("test1"); | ||
var hash2 = hashProvider.ComputeHash("test2"); | ||
|
||
// Act && Assert | ||
Assert.NotEqual(hash1, hash2); | ||
} | ||
|
||
[Fact] | ||
public void ComputeHash_ReturnsDifferentHash_ForDifferentByteArrayData() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
var data1 = "test1"u8.ToArray(); | ||
var data2 = "test2"u8.ToArray(); | ||
|
||
// Act | ||
var hash1 = hashProvider.ComputeHash(data1); | ||
var hash2 = hashProvider.ComputeHash(data2); | ||
|
||
// Act && Assert | ||
Assert.NotEqual(hash1, hash2); | ||
} | ||
|
||
[Fact] | ||
public void ComputeHash_ReturnsDifferentHash_ForDifferentByteArrayDataWithOffset() | ||
{ | ||
// Arrange | ||
var hashProvider = new XxHash64Unsafe(); | ||
var data1 = "test1"u8.ToArray(); | ||
var data2 = "test2"u8.ToArray(); | ||
|
||
// Act | ||
var hash1 = hashProvider.ComputeHash(data1, 0, data1.Length, 0); | ||
var hash2 = hashProvider.ComputeHash(data2, 0, data2.Length, 0); | ||
|
||
// Act && Assert | ||
Assert.NotEqual(hash1, hash2); | ||
} | ||
} |
Unchanged files with check annotations Beta
EFServiceProvider.RunInContext(context => | ||
{ | ||
context.People.Where(a => a.Id > 500).BatchDelete(); | ||
context.People.Where(a => a.Id <= 500) | ||
.BatchUpdate(a => new Person { Name = a.Name + "-Test" }); | ||
//`EFCore.BulkExtensions` doesn't pass all of its executed SQL commands such as `BulkInsert` through the interceptors. |
private static void runBenchmarks() | ||
{ | ||
var config = ManualConfig.Create(DefaultConfig.Instance) | ||
Check warning on line 22 in src/Tests/EFCoreSecondLevelCacheInterceptor.PerformanceTests/Program.cs GitHub Actions / Analyze (csharp)
Check warning on line 22 in src/Tests/EFCoreSecondLevelCacheInterceptor.PerformanceTests/Program.cs GitHub Actions / Analyze (csharp)
Check warning on line 22 in src/Tests/EFCoreSecondLevelCacheInterceptor.PerformanceTests/Program.cs GitHub Actions / Analyze (csharp)
Check warning on line 22 in src/Tests/EFCoreSecondLevelCacheInterceptor.PerformanceTests/Program.cs GitHub Actions / Analyze (csharp)
Check warning on line 22 in src/Tests/EFCoreSecondLevelCacheInterceptor.PerformanceTests/Program.cs GitHub Actions / Analyze (csharp)
Check warning on line 22 in src/Tests/EFCoreSecondLevelCacheInterceptor.PerformanceTests/Program.cs GitHub Actions / Analyze (csharp)
Check warning on line 22 in src/Tests/EFCoreSecondLevelCacheInterceptor.PerformanceTests/Program.cs GitHub Actions / Analyze (csharp)
Check warning on line 22 in src/Tests/EFCoreSecondLevelCacheInterceptor.PerformanceTests/Program.cs GitHub Actions / Analyze (csharp)
|
||
.With(BenchmarkDotNet.Analysers.EnvironmentAnalyser.Default) | ||
.With(BenchmarkDotNet.Exporters.MarkdownExporter.GitHub) | ||
.With(BenchmarkDotNet.Diagnosers.MemoryDiagnoser.Default) |
Check warning
Code scanning / CodeQL
Reference equality test on System.Object Warning