by Guest » 07 Jan 2025, 11:01
Ich erstelle einen C#-Hintergrunddienst mit der folgenden Definition
Code: Select all
public class SqsBackgroundService(
IPollingConfiguration pollingSettings,
IServiceProvider serviceProvider,
IMessagingService messagingService,
IOptions options,
ILogger logger) : RecurringBackgroundService(pollingSettings, serviceProvider)
where TConfig : QueueConfiguration
where TProcessor : IMessageProcessor
{
internal override async Task Execute(IServiceProvider provider, CancellationToken cancellationToken)
{
using (var scope = provider.CreateScope())
{
var messageProcessor = scope.ServiceProvider.GetService();
if (messageProcessor == null)
{
throw new NullReferenceException("Unable to resolve message processor");
}
var result = await messageProcessor.ProcessMessage(message, token);
if (result.ProcessSuccessfully)
....
}
}
}
}
Dies wird von einem Listener verwendet
Code: Select all
public class ClientEntityListener(
IServiceProvider serviceProvider,
IOptions backgroundConfig,
IOptions queueConfig,
ILogger logger) :
SqsBackgroundService(
backgroundConfig.Value.ClientEntityPollingConfiguration,
serviceProvider,
serviceProvider.GetRequiredService(),
queueConfig,
logger)
{
}
erbt eine Basisklasse IMessageProcessor, die der erwartete TProcessor-Wert im SqsBackgroundService ist. Der Test wird wie folgt aufgebaut und aufgerufen.
Code: Select all
var mockServiceProvider = new Mock();
var mockServiceScope = new Mock();
mockServiceScope.Setup(x => x.ServiceProvider).Returns(mockServiceProvider.Object);
var mockServiceScopeFactory = new Mock();
mockServiceScopeFactory
.Setup(x => x.CreateScope())
.Returns(mockServiceScope.Object);
mockServiceProvider
.Setup(x => x.GetService(typeof(IServiceScopeFactory)))
.Returns(mockServiceScopeFactory.Object);
....
var messageResult = new MessageResult(true);
var mockClientEntityProcessor = new Mock();
mockClientEntityProcessor.Setup(x => x.ProcessMessage(
It.IsAny(),
It.IsAny()))
.ReturnsAsync(messageResult);
mockServiceProvider
.Setup(x => x.GetService(typeof(IClientEntityProcessor)))
.Returns(mockClientEntityProcessor.Object);
....
var service = new ClientEntityListener(
mockServiceProvider.Object,
_mockBackgroundConfig.Object,
_mockQueueConfig.Object,
mockBaseLogger.Object);
await service.Execute(mockServiceProvider.Object, CancellationToken.None);
Wenn dieser Test ausgeführt wird, wird die Zeile
Code: Select all
var result = await messageProcessor.ProcessMessage(message, token);
im SqsBackgroundService gibt null anstelle des erwarteten messageResult zurück. Ich kann unter den Scheinaufrufen sehen, dass IMessageProcessor.ProcessMessage aufgerufen wird. Wenn ich jedoch im Test-Setup dieselben Zeilen ausführe, sind diese
Code: Select all
var scope = mockServiceProvider.Object.CreateScope();
var processor = scope.ServiceProvider.GetService();
var test = await processor.ProcessMessage(messages[0], CancellationToken.None);
Ich kann sehen, dass das Ergebnis wie erwartet das messageResult ist, der Aufruf auf dem Mock ist jedoch IClientEntityProcessor.ProcessMessage. Dies lässt mich vermuten, dass das Problem darin besteht, dass die Basismethode von IMessageProcessor.ProcessMessage aufgerufen wird, die im aktuellen Setup nicht verspottet wird. Meine Versuche, den aufgerufenen IMessageProcessor zu verspotten, sind fehlgeschlagen. Gibt es eine Möglichkeit, dies zu verspotten, um die erwartete Leistung zu erbringen?
Ich erstelle einen C#-Hintergrunddienst mit der folgenden Definition
[code]public class SqsBackgroundService(
IPollingConfiguration pollingSettings,
IServiceProvider serviceProvider,
IMessagingService messagingService,
IOptions options,
ILogger logger) : RecurringBackgroundService(pollingSettings, serviceProvider)
where TConfig : QueueConfiguration
where TProcessor : IMessageProcessor
{
internal override async Task Execute(IServiceProvider provider, CancellationToken cancellationToken)
{
using (var scope = provider.CreateScope())
{
var messageProcessor = scope.ServiceProvider.GetService();
if (messageProcessor == null)
{
throw new NullReferenceException("Unable to resolve message processor");
}
var result = await messageProcessor.ProcessMessage(message, token);
if (result.ProcessSuccessfully)
....
}
}
}
}
[/code]
Dies wird von einem Listener verwendet
[code]public class ClientEntityListener(
IServiceProvider serviceProvider,
IOptions backgroundConfig,
IOptions queueConfig,
ILogger logger) :
SqsBackgroundService(
backgroundConfig.Value.ClientEntityPollingConfiguration,
serviceProvider,
serviceProvider.GetRequiredService(),
queueConfig,
logger)
{
}
[/code]
[code]IClientEntityProcessor[/code] erbt eine Basisklasse IMessageProcessor, die der erwartete TProcessor-Wert im SqsBackgroundService ist. Der Test wird wie folgt aufgebaut und aufgerufen.
[code] var mockServiceProvider = new Mock();
var mockServiceScope = new Mock();
mockServiceScope.Setup(x => x.ServiceProvider).Returns(mockServiceProvider.Object);
var mockServiceScopeFactory = new Mock();
mockServiceScopeFactory
.Setup(x => x.CreateScope())
.Returns(mockServiceScope.Object);
mockServiceProvider
.Setup(x => x.GetService(typeof(IServiceScopeFactory)))
.Returns(mockServiceScopeFactory.Object);
....
var messageResult = new MessageResult(true);
var mockClientEntityProcessor = new Mock();
mockClientEntityProcessor.Setup(x => x.ProcessMessage(
It.IsAny(),
It.IsAny()))
.ReturnsAsync(messageResult);
mockServiceProvider
.Setup(x => x.GetService(typeof(IClientEntityProcessor)))
.Returns(mockClientEntityProcessor.Object);
....
var service = new ClientEntityListener(
mockServiceProvider.Object,
_mockBackgroundConfig.Object,
_mockQueueConfig.Object,
mockBaseLogger.Object);
await service.Execute(mockServiceProvider.Object, CancellationToken.None);
[/code]
Wenn dieser Test ausgeführt wird, wird die Zeile
[code]var result = await messageProcessor.ProcessMessage(message, token);[/code] im SqsBackgroundService gibt null anstelle des erwarteten messageResult zurück. Ich kann unter den Scheinaufrufen sehen, dass IMessageProcessor.ProcessMessage aufgerufen wird. Wenn ich jedoch im Test-Setup dieselben Zeilen ausführe, sind diese
[code] var scope = mockServiceProvider.Object.CreateScope();
var processor = scope.ServiceProvider.GetService();
var test = await processor.ProcessMessage(messages[0], CancellationToken.None);
[/code]
Ich kann sehen, dass das Ergebnis wie erwartet das messageResult ist, der Aufruf auf dem Mock ist jedoch IClientEntityProcessor.ProcessMessage. Dies lässt mich vermuten, dass das Problem darin besteht, dass die Basismethode von IMessageProcessor.ProcessMessage aufgerufen wird, die im aktuellen Setup nicht verspottet wird. Meine Versuche, den aufgerufenen IMessageProcessor zu verspotten, sind fehlgeschlagen. Gibt es eine Möglichkeit, dies zu verspotten, um die erwartete Leistung zu erbringen?