added basic unit tests
This commit is contained in:
parent
85876688a9
commit
f59a6da2da
@ -16,10 +16,10 @@ namespace Provider
|
|||||||
|
|
||||||
public RedisStreamAdapter(IDatabase database, string providerName, HashRingBasedStreamQueueMapper hashRingBasedStreamQueueMapper, ILoggerFactory loggerFactory)
|
public RedisStreamAdapter(IDatabase database, string providerName, HashRingBasedStreamQueueMapper hashRingBasedStreamQueueMapper, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database ?? throw new ArgumentNullException(nameof(database));
|
||||||
_providerName = providerName;
|
_providerName = providerName ?? throw new ArgumentNullException(nameof(providerName));
|
||||||
_hashRingBasedStreamQueueMapper = hashRingBasedStreamQueueMapper;
|
_hashRingBasedStreamQueueMapper = hashRingBasedStreamQueueMapper ?? throw new ArgumentNullException(nameof(hashRingBasedStreamQueueMapper));
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
|
||||||
_logger = loggerFactory.CreateLogger<RedisStreamAdapter>();
|
_logger = loggerFactory.CreateLogger<RedisStreamAdapter>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,11 +24,16 @@ namespace Provider
|
|||||||
HashRingStreamQueueMapperOptions hashRingStreamQueueMapperOptions
|
HashRingStreamQueueMapperOptions hashRingStreamQueueMapperOptions
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_connectionMultiplexer = connectionMultiplexer;
|
if (hashRingStreamQueueMapperOptions is null)
|
||||||
_loggerFactory = loggerFactory;
|
{
|
||||||
_providerName = providerName;
|
throw new ArgumentNullException(nameof(hashRingStreamQueueMapperOptions));
|
||||||
_streamFailureHandler = streamFailureHandler;
|
}
|
||||||
_simpleQueueCacheOptions = simpleQueueCacheOptions;
|
|
||||||
|
_connectionMultiplexer = connectionMultiplexer ?? throw new ArgumentNullException(nameof(connectionMultiplexer));
|
||||||
|
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
|
||||||
|
_providerName = providerName ?? throw new ArgumentNullException(nameof(providerName));
|
||||||
|
_streamFailureHandler = streamFailureHandler ?? throw new ArgumentNullException(nameof(streamFailureHandler));
|
||||||
|
_simpleQueueCacheOptions = simpleQueueCacheOptions ?? throw new ArgumentNullException(nameof(simpleQueueCacheOptions));
|
||||||
_hashRingBasedStreamQueueMapper = new HashRingBasedStreamQueueMapper(hashRingStreamQueueMapperOptions, providerName);
|
_hashRingBasedStreamQueueMapper = new HashRingBasedStreamQueueMapper(hashRingStreamQueueMapperOptions, providerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ namespace Provider
|
|||||||
|
|
||||||
public RedisStreamFailureHandler(ILogger<RedisStreamFailureHandler> logger)
|
public RedisStreamFailureHandler(ILogger<RedisStreamFailureHandler> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShouldFaultSubsriptionOnError => true;
|
public bool ShouldFaultSubsriptionOnError => true;
|
||||||
|
|||||||
@ -16,8 +16,8 @@ namespace Provider
|
|||||||
public RedisStreamReceiver(QueueId queueId, IDatabase database, ILogger<RedisStreamReceiver> logger)
|
public RedisStreamReceiver(QueueId queueId, IDatabase database, ILogger<RedisStreamReceiver> logger)
|
||||||
{
|
{
|
||||||
_queueId = queueId;
|
_queueId = queueId;
|
||||||
_database = database;
|
_database = database ?? throw new ArgumentNullException(nameof(database));
|
||||||
_logger = logger;
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IList<IBatchContainer>?> GetQueueMessagesAsync(int maxCount)
|
public async Task<IList<IBatchContainer>?> GetQueueMessagesAsync(int maxCount)
|
||||||
|
|||||||
@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csp
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Provider", "Provider\Provider.csproj", "{70F8E685-F662-4225-A60C-D318E0C6ED18}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Provider", "Provider\Provider.csproj", "{70F8E685-F662-4225-A60C-D318E0C6ED18}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedisStreamsProvider.UnitTests", "RedisStreamsProvider.UnitTests\RedisStreamsProvider.UnitTests.csproj", "{DF927C2B-A141-4476-86CF-3B4DC8ECB4DE}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -27,6 +29,10 @@ Global
|
|||||||
{70F8E685-F662-4225-A60C-D318E0C6ED18}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{70F8E685-F662-4225-A60C-D318E0C6ED18}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{70F8E685-F662-4225-A60C-D318E0C6ED18}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{70F8E685-F662-4225-A60C-D318E0C6ED18}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{70F8E685-F662-4225-A60C-D318E0C6ED18}.Release|Any CPU.Build.0 = Release|Any CPU
|
{70F8E685-F662-4225-A60C-D318E0C6ED18}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DF927C2B-A141-4476-86CF-3B4DC8ECB4DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DF927C2B-A141-4476-86CF-3B4DC8ECB4DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DF927C2B-A141-4476-86CF-3B4DC8ECB4DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DF927C2B-A141-4476-86CF-3B4DC8ECB4DE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
48
RedisStreamsProvider.UnitTests/RedisStreamAdapterTests.cs
Normal file
48
RedisStreamsProvider.UnitTests/RedisStreamAdapterTests.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using Moq;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Orleans.Streams;
|
||||||
|
using Xunit;
|
||||||
|
using Provider;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Orleans.Configuration;
|
||||||
|
|
||||||
|
namespace RedisStreamsProvider.UnitTests
|
||||||
|
{
|
||||||
|
public class RedisStreamAdapterTests
|
||||||
|
{
|
||||||
|
private readonly Mock<IDatabase> _mockDatabase;
|
||||||
|
private readonly Mock<HashRingBasedStreamQueueMapper> _mockQueueMapper;
|
||||||
|
private readonly Mock<ILoggerFactory> _mockLoggerFactory;
|
||||||
|
private readonly RedisStreamAdapter _adapter;
|
||||||
|
|
||||||
|
public RedisStreamAdapterTests()
|
||||||
|
{
|
||||||
|
_mockDatabase = new Mock<IDatabase>();
|
||||||
|
var options = new HashRingStreamQueueMapperOptions { TotalQueueCount = 1 };
|
||||||
|
_mockQueueMapper = new Mock<HashRingBasedStreamQueueMapper>(options, "queueNamePrefix");
|
||||||
|
_mockLoggerFactory = new Mock<ILoggerFactory>();
|
||||||
|
|
||||||
|
_adapter = new RedisStreamAdapter(_mockDatabase.Object, "TestProvider", _mockQueueMapper.Object, _mockLoggerFactory.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializeProperties()
|
||||||
|
{
|
||||||
|
Assert.Equal("TestProvider", _adapter.Name);
|
||||||
|
Assert.False(_adapter.IsRewindable);
|
||||||
|
Assert.Equal(StreamProviderDirection.ReadWrite, _adapter.Direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreateReceiver_ShouldReturnRedisStreamReceiver()
|
||||||
|
{
|
||||||
|
var queueId = QueueId.GetQueueId("queueName", 0, 1);
|
||||||
|
var receiver = _adapter.CreateReceiver(queueId);
|
||||||
|
|
||||||
|
Assert.NotNull(receiver);
|
||||||
|
Assert.IsType<RedisStreamReceiver>(receiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
using Provider;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace RedisStreamsProvider.UnitTests
|
||||||
|
{
|
||||||
|
public class RedisStreamBatchContainerTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializeProperties()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var streamEntry = new StreamEntry("1-0", new NameValueEntry[]
|
||||||
|
{
|
||||||
|
new NameValueEntry("namespace", "testNamespace"),
|
||||||
|
new NameValueEntry("key", "testKey"),
|
||||||
|
new NameValueEntry("type", "TestEvent"),
|
||||||
|
new NameValueEntry("data", JsonSerializer.Serialize(new TestEvent { Id = 1, Name = "Test" }))
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var container = new RedisStreamBatchContainer(streamEntry);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("testNamespace", container.StreamId.GetNamespace());
|
||||||
|
Assert.Equal("testKey", container.StreamId.GetKeyAsString());
|
||||||
|
Assert.Equal(streamEntry.Id.ToString().Split('-').First(), container.SequenceToken.SequenceNumber.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetEvents_ShouldReturnDeserializedEvents()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var streamEntry = new StreamEntry("1-0", new NameValueEntry[]
|
||||||
|
{
|
||||||
|
new NameValueEntry("namespace", "testNamespace"),
|
||||||
|
new NameValueEntry("key", "testKey"),
|
||||||
|
new NameValueEntry("type", "TestEvent"),
|
||||||
|
new NameValueEntry("data", JsonSerializer.Serialize(new TestEvent { Id = 1, Name = "Test" }))
|
||||||
|
});
|
||||||
|
var container = new RedisStreamBatchContainer(streamEntry);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var events = container.GetEvents<TestEvent>().ToList();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Single(events);
|
||||||
|
Assert.Equal(1, events[0].Item1.Id);
|
||||||
|
Assert.Equal("Test", events[0].Item1.Name);
|
||||||
|
Assert.Equal(streamEntry.Id.ToString().Split('-').First(), events[0].Item2.SequenceNumber.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ImportRequestContext_ShouldReturnFalse()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var streamEntry = new StreamEntry("1-0", new NameValueEntry[]
|
||||||
|
{
|
||||||
|
new NameValueEntry("namespace", "testNamespace"),
|
||||||
|
new NameValueEntry("key", "testKey"),
|
||||||
|
new NameValueEntry("type", "TestEvent"),
|
||||||
|
new NameValueEntry("data", JsonSerializer.Serialize(new TestEvent { Id = 1, Name = "Test" }))
|
||||||
|
});
|
||||||
|
var container = new RedisStreamBatchContainer(streamEntry);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = container.ImportRequestContext();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestEvent
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
90
RedisStreamsProvider.UnitTests/RedisStreamFactoryTests.cs
Normal file
90
RedisStreamsProvider.UnitTests/RedisStreamFactoryTests.cs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Moq;
|
||||||
|
using Orleans.Configuration;
|
||||||
|
using Orleans.Providers.Streams.Common;
|
||||||
|
using Orleans.Streams;
|
||||||
|
using Provider;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace RedisStreamsProvider.UnitTests
|
||||||
|
{
|
||||||
|
public class RedisStreamFactoryTests
|
||||||
|
{
|
||||||
|
private readonly Mock<IConnectionMultiplexer> _mockConnectionMultiplexer;
|
||||||
|
private readonly Mock<ILoggerFactory> _mockLoggerFactory;
|
||||||
|
private readonly Mock<IServiceProvider> _mockServiceProvider;
|
||||||
|
private readonly Mock<IStreamFailureHandler> _mockStreamFailureHandler;
|
||||||
|
private readonly SimpleQueueCacheOptions _simpleQueueCacheOptions;
|
||||||
|
private readonly HashRingStreamQueueMapperOptions _hashRingStreamQueueMapperOptions;
|
||||||
|
private readonly string _providerName = "TestProvider";
|
||||||
|
|
||||||
|
public RedisStreamFactoryTests()
|
||||||
|
{
|
||||||
|
_mockConnectionMultiplexer = new Mock<IConnectionMultiplexer>();
|
||||||
|
_mockConnectionMultiplexer.Setup(x => x.GetDatabase(It.IsAny<int>(), It.IsAny<object>())).Returns(new Mock<IDatabase>().Object);
|
||||||
|
|
||||||
|
_mockLoggerFactory = new Mock<ILoggerFactory>();
|
||||||
|
_mockServiceProvider = new Mock<IServiceProvider>();
|
||||||
|
_mockStreamFailureHandler = new Mock<IStreamFailureHandler>();
|
||||||
|
_simpleQueueCacheOptions = new SimpleQueueCacheOptions();
|
||||||
|
_hashRingStreamQueueMapperOptions = new HashRingStreamQueueMapperOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldThrowArgumentNullException_WhenAnyArgumentIsNull()
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentNullException>(() => new RedisStreamFactory(null, _mockLoggerFactory.Object, _providerName, _mockStreamFailureHandler.Object, _simpleQueueCacheOptions, _hashRingStreamQueueMapperOptions));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => new RedisStreamFactory(_mockConnectionMultiplexer.Object, null, _providerName, _mockStreamFailureHandler.Object, _simpleQueueCacheOptions, _hashRingStreamQueueMapperOptions));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => new RedisStreamFactory(_mockConnectionMultiplexer.Object, _mockLoggerFactory.Object, null, _mockStreamFailureHandler.Object, _simpleQueueCacheOptions, _hashRingStreamQueueMapperOptions));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => new RedisStreamFactory(_mockConnectionMultiplexer.Object, _mockLoggerFactory.Object, _providerName, null, _simpleQueueCacheOptions, _hashRingStreamQueueMapperOptions));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => new RedisStreamFactory(_mockConnectionMultiplexer.Object, _mockLoggerFactory.Object, _providerName, _mockStreamFailureHandler.Object, null, _hashRingStreamQueueMapperOptions));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => new RedisStreamFactory(_mockConnectionMultiplexer.Object, _mockLoggerFactory.Object, _providerName, _mockStreamFailureHandler.Object, _simpleQueueCacheOptions, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateAdapter_ShouldReturnRedisStreamAdapterInstance()
|
||||||
|
{
|
||||||
|
var factory = new RedisStreamFactory(_mockConnectionMultiplexer.Object, _mockLoggerFactory.Object, _providerName, _mockStreamFailureHandler.Object, _simpleQueueCacheOptions, _hashRingStreamQueueMapperOptions);
|
||||||
|
|
||||||
|
var adapter = await factory.CreateAdapter();
|
||||||
|
|
||||||
|
Assert.NotNull(adapter);
|
||||||
|
Assert.IsType<RedisStreamAdapter>(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetDeliveryFailureHandler_ShouldReturnStreamFailureHandler()
|
||||||
|
{
|
||||||
|
var factory = new RedisStreamFactory(_mockConnectionMultiplexer.Object, _mockLoggerFactory.Object, _providerName, _mockStreamFailureHandler.Object, _simpleQueueCacheOptions, _hashRingStreamQueueMapperOptions);
|
||||||
|
|
||||||
|
var handler = await factory.GetDeliveryFailureHandler(new QueueId());
|
||||||
|
|
||||||
|
Assert.NotNull(handler);
|
||||||
|
Assert.Equal(_mockStreamFailureHandler.Object, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetQueueAdapterCache_ShouldReturnSimpleQueueAdapterCacheInstance()
|
||||||
|
{
|
||||||
|
var factory = new RedisStreamFactory(_mockConnectionMultiplexer.Object, _mockLoggerFactory.Object, _providerName, _mockStreamFailureHandler.Object, _simpleQueueCacheOptions, _hashRingStreamQueueMapperOptions);
|
||||||
|
|
||||||
|
var cache = factory.GetQueueAdapterCache();
|
||||||
|
|
||||||
|
Assert.NotNull(cache);
|
||||||
|
Assert.IsType<SimpleQueueAdapterCache>(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetStreamQueueMapper_ShouldReturnHashRingBasedStreamQueueMapperInstance()
|
||||||
|
{
|
||||||
|
var factory = new RedisStreamFactory(_mockConnectionMultiplexer.Object, _mockLoggerFactory.Object, _providerName, _mockStreamFailureHandler.Object, _simpleQueueCacheOptions, _hashRingStreamQueueMapperOptions);
|
||||||
|
|
||||||
|
var mapper = factory.GetStreamQueueMapper();
|
||||||
|
|
||||||
|
Assert.NotNull(mapper);
|
||||||
|
Assert.IsType<HashRingBasedStreamQueueMapper>(mapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
RedisStreamsProvider.UnitTests/RedisStreamReceiverTests.cs
Normal file
104
RedisStreamsProvider.UnitTests/RedisStreamReceiverTests.cs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Moq;
|
||||||
|
using Orleans.Streams;
|
||||||
|
using Provider;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace RedisStreamsProvider.UnitTests
|
||||||
|
{
|
||||||
|
public class RedisStreamReceiverTests
|
||||||
|
{
|
||||||
|
private readonly Mock<IDatabase> _mockDatabase;
|
||||||
|
private readonly Mock<ILogger<RedisStreamReceiver>> _mockLogger;
|
||||||
|
private readonly QueueId _queueId;
|
||||||
|
private readonly RedisStreamReceiver _receiver;
|
||||||
|
|
||||||
|
public RedisStreamReceiverTests()
|
||||||
|
{
|
||||||
|
_mockDatabase = new Mock<IDatabase>();
|
||||||
|
_mockLogger = new Mock<ILogger<RedisStreamReceiver>>();
|
||||||
|
_queueId = QueueId.GetQueueId("testQueue", 0, 0); // Added the missing 'hash' parameter
|
||||||
|
_receiver = new RedisStreamReceiver(_queueId, _mockDatabase.Object, _mockLogger.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetQueueMessagesAsync_ReturnsBatches()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var streamEntries = new[]
|
||||||
|
{
|
||||||
|
new StreamEntry("1-0", new NameValueEntry[2] {new NameValueEntry("namespace", "testNamespace"),
|
||||||
|
new NameValueEntry("key", "testKey")}),
|
||||||
|
new StreamEntry("2-0", new NameValueEntry[2] {new NameValueEntry("namespace", "testNamespace"),
|
||||||
|
new NameValueEntry("key", "testKey")})
|
||||||
|
};
|
||||||
|
_mockDatabase.Setup(db => db.StreamReadGroupAsync(
|
||||||
|
It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<RedisValue>(), It.IsAny<RedisValue?>(),
|
||||||
|
It.IsAny<int?>(), It.IsAny<bool>(), CommandFlags.None))
|
||||||
|
.ReturnsAsync(streamEntries);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _receiver.GetQueueMessagesAsync(10);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.Equal(2, result.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Initialize_CreatesConsumerGroup()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockDatabase.Setup(db => db.StreamCreateConsumerGroupAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<RedisValue>(), It.IsAny<bool>(), CommandFlags.None))
|
||||||
|
.ReturnsAsync(true);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _receiver.Initialize(TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockDatabase.Verify(db => db.StreamCreateConsumerGroupAsync(_queueId.ToString(), "consumer", "$", true, CommandFlags.None), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task MessagesDeliveredAsync_AcknowledgesMessages()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var messages = new List<IBatchContainer>
|
||||||
|
{
|
||||||
|
new RedisStreamBatchContainer(new StreamEntry("1-0", new NameValueEntry[2] {new NameValueEntry("namespace", "testNamespace"),
|
||||||
|
new NameValueEntry("key", "testKey")})),
|
||||||
|
new RedisStreamBatchContainer(new StreamEntry("2-0", new NameValueEntry[2] {new NameValueEntry("namespace", "testNamespace"),
|
||||||
|
new NameValueEntry("key", "testKey")}))
|
||||||
|
};
|
||||||
|
_mockDatabase.Setup(db => db.StreamAcknowledgeAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<RedisValue>(), CommandFlags.None))
|
||||||
|
.ReturnsAsync(2);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _receiver.MessagesDeliveredAsync(messages);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockDatabase.Verify(db => db.StreamAcknowledgeAsync(_queueId.ToString(), "consumer", "1-0", CommandFlags.None), Times.Once);
|
||||||
|
_mockDatabase.Verify(db => db.StreamAcknowledgeAsync(_queueId.ToString(), "consumer", "2-0", CommandFlags.None), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Shutdown_WaitsForPendingTasks()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tcs = new TaskCompletionSource<StreamEntry[]>();
|
||||||
|
_mockDatabase.Setup(db => db.StreamReadGroupAsync(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<RedisValue>(), It.IsAny<RedisValue>(), It.IsAny<int>(), CommandFlags.None))
|
||||||
|
.Returns(tcs.Task);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var getMessagesTask = _receiver.GetQueueMessagesAsync(10);
|
||||||
|
await _receiver.Shutdown(TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(getMessagesTask.IsCompleted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
132
RedisStreamsProvider.UnitTests/RedisStreamSequenceTokenTests.cs
Normal file
132
RedisStreamsProvider.UnitTests/RedisStreamSequenceTokenTests.cs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
using Xunit;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using Provider;
|
||||||
|
using Orleans.Streams;
|
||||||
|
using System;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace Provider.Tests
|
||||||
|
{
|
||||||
|
public class RedisStreamSequenceTokenTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializeProperties_FromRedisValue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var redisValue = new RedisValue("123-456");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var token = new RedisStreamSequenceToken(redisValue);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(123, token.SequenceNumber);
|
||||||
|
Assert.Equal(456, token.EventIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldInitializeProperties_FromParameters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
long sequenceNumber = 123;
|
||||||
|
int eventIndex = 456;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var token = new RedisStreamSequenceToken(sequenceNumber, eventIndex);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(sequenceNumber, token.SequenceNumber);
|
||||||
|
Assert.Equal(eventIndex, token.EventIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CompareTo_ShouldReturnZero_ForEqualTokens()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var token1 = new RedisStreamSequenceToken(123, 456);
|
||||||
|
var token2 = new RedisStreamSequenceToken(123, 456);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = token1.CompareTo(token2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(0, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CompareTo_ShouldReturnPositive_ForGreaterToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var token1 = new RedisStreamSequenceToken(123, 456);
|
||||||
|
var token2 = new RedisStreamSequenceToken(123, 455);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = token1.CompareTo(token2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CompareTo_ShouldReturnNegative_ForLesserToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var token1 = new RedisStreamSequenceToken(123, 455);
|
||||||
|
var token2 = new RedisStreamSequenceToken(123, 456);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = token1.CompareTo(token2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equals_ShouldReturnTrue_ForEqualTokens()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var token1 = new RedisStreamSequenceToken(123, 456);
|
||||||
|
var token2 = new RedisStreamSequenceToken(123, 456);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = token1.Equals(token2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equals_ShouldReturnFalse_ForDifferentTokens()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var token1 = new RedisStreamSequenceToken(123, 456);
|
||||||
|
var token2 = new RedisStreamSequenceToken(123, 457);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = token1.Equals(token2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CompareTo_ShouldThrowArgumentNullException_ForNullToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var token = new RedisStreamSequenceToken(123, 456);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
Assert.Throws<ArgumentNullException>(() => token.CompareTo(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CompareTo_ShouldThrowArgumentException_ForInvalidTokenType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var token = new RedisStreamSequenceToken(123, 456);
|
||||||
|
var invalidToken = new Mock<StreamSequenceToken>().Object;
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
Assert.Throws<ArgumentException>(() => token.CompareTo(invalidToken));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Provider\Provider.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Loading…
x
Reference in New Issue
Block a user