Created
August 7, 2022 10:27
-
-
Save duongphuhiep/15f223437bfd88a05de09c420473133b to your computer and use it in GitHub Desktop.
Masstransit 8 TestHarness and Moq.Automocker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using MassTransit; | |
using MassTransit.Testing; | |
using Microsoft.Extensions.DependencyInjection; | |
using Moq; | |
using Moq.AutoMock; | |
using System.Threading.Tasks; | |
using Xunit; | |
namespace HiepTest; | |
public record SubmitOrder(long Id, string CustomerName); | |
public record OrderSubmitted(string SubmitReference); | |
public interface INotifier | |
{ | |
public Task<string> Notify(string content); | |
} | |
public interface IStockChecker { } | |
public interface IFidelityUpdater { } | |
public interface IPromotionManager { } | |
public class SubmitOrderConsumer : IConsumer<SubmitOrder> | |
{ | |
private readonly INotifier notifier; | |
public SubmitOrderConsumer(INotifier notifier, IStockChecker stockChecker, IFidelityUpdater fidelityUpdater, IPromotionManager promotionManager) | |
{ | |
this.notifier = notifier; | |
} | |
public async Task Consume(ConsumeContext<SubmitOrder> context) | |
{ | |
var input = context.Message; | |
await notifier.Notify("Order submitted"); | |
var output = new OrderSubmitted($"{input.Id}.{input.CustomerName}"); | |
await context.RespondAsync(output); | |
} | |
} | |
public class SampleUnitTest | |
{ | |
/// <summary> | |
/// Treat the consumer as a normal class and unit test it. | |
/// </summary> | |
[Fact] | |
public async Task NormalTest() | |
{ | |
//ARRANGE | |
AutoMocker mocker = new AutoMocker(); | |
var consumerUnderTest = mocker.CreateInstance<SubmitOrderConsumer>(); | |
mocker.GetMock<INotifier>().Setup(m => m.Notify(It.IsAny<string>())).ReturnsAsync("OK"); | |
var sampleInput = new SubmitOrder(1, "Hiep"); | |
var consumeContextMock = mocker.GetMock<ConsumeContext<SubmitOrder>>(); | |
consumeContextMock.SetupGet(x => x.Message).Returns(sampleInput); | |
//ACT | |
await consumerUnderTest.Consume(consumeContextMock.Object); | |
//ASSERT | |
//that the customer is notified "Order submitted" | |
mocker.GetMock<INotifier>().Verify(m => m.Notify(It.Is<string>(v => v == "Order submitted"))); | |
//that the response is sent back, and it contains the customer's name | |
consumeContextMock.Verify(m => m.RespondAsync(It.Is<OrderSubmitted>(r => r.SubmitReference.Contains(sampleInput.CustomerName)))); | |
} | |
[Fact] | |
public async Task UseTestHarness() | |
{ | |
//ARRANGE | |
AutoMocker mocker = new AutoMocker(); | |
var consumerUnderTest = mocker.CreateInstance<SubmitOrderConsumer>(); | |
await using var provider = new ServiceCollection() | |
.AddMassTransitTestHarness(cfg => | |
{ | |
cfg.AddConsumer<SubmitOrderConsumer>(); | |
}) | |
.AddSingleton(consumerUnderTest) | |
.BuildServiceProvider(true); | |
var harness = provider.GetRequiredService<ITestHarness>(); | |
await harness.Start(); | |
var client = harness.GetRequestClient<SubmitOrder>(); | |
var sampleInput = new SubmitOrder(1, "Hiep"); | |
//ACT | |
var response = await client.GetResponse<OrderSubmitted>(sampleInput); | |
//ASSERT | |
//that the sampleInput is consumed (there exist a SubmitOrder in the ReceivedMessageList) | |
Assert.True(await harness.Consumed.Any<SubmitOrder>()); | |
Assert.True(await harness.Consumed.Any<SubmitOrder>(x => ((SubmitOrder)x.MessageObject).Id == sampleInput.Id)); | |
//that the SubmitOrderConsumer is invoked (in case there are multiple Consumer) | |
var consumerHarness = harness.GetConsumerHarness<SubmitOrderConsumer>(); | |
Assert.True(await consumerHarness.Consumed.Any<SubmitOrder>()); | |
Assert.True(await consumerHarness.Consumed.Any<SubmitOrder>(x => ((SubmitOrder)x.MessageObject).Id == sampleInput.Id)); | |
//that a response is sent back in the harness (there exist a OrderSubmitted in the SentMessageList) | |
Assert.True(await harness.Sent.Any<OrderSubmitted>()); | |
Assert.True(await harness.Sent.Any<OrderSubmitted>(x => ((OrderSubmitted)x.MessageObject).SubmitReference.Contains(sampleInput.CustomerName))); | |
//that the customer is notified "Order submitted" | |
mocker.GetMock<INotifier>().Verify(m => m.Notify(It.Is<string>(v => v == "Order submitted"))); | |
//that the response contains the customer's name | |
Assert.Contains(sampleInput.CustomerName, response.Message.SubmitReference); | |
} | |
} |
To resume the problem & solution
https://stackoverflow.com/questions/73267173/how-to-create-masstransits-test-harness-with-automock
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
We can extract the Harness Creation to a generic library
Usage:
So the above codes of the
UseTestHarness
test is reduced to