如何模拟 Azure 队列存储以进行单元测试?
Posted
技术标签:
【中文标题】如何模拟 Azure 队列存储以进行单元测试?【英文标题】:How to mock Azure Queue storage for unit test? 【发布时间】:2020-11-27 14:39:47 【问题描述】:我想模拟 QueueMessage 进行单元测试,但我找不到任何要模拟的库
public async Task<QueueMessage[]> ReceiveMessagesAsync(QueueClient queue)
QueueProperties properties = queue.GetProperties();
// Retrieve the cached approximate message count.
int cachedMessagesCount = properties.ApproximateMessagesCount;
QueueMessage[] queueMessages =new QueueMessage[cachedMessagesCount];
int num = cachedMessagesCount / 32;
for (int i = 0; i < num + 1; i++)
var messages = await queue.ReceiveMessagesAsync(maxMessages: 32);
messages.Value.CopyTo(queueMessages,i*32);
return queueMessages;
【问题讨论】:
模拟 EAI 系统 的各个方面有什么意义?消息只是信封。你想要有效载荷。测试有效载荷的处理程序不是更好吗? well-written system 的业务逻辑应该与任何 EAI 系统解耦 @MickyD 感谢您的评论!你真的明白了,我通过返回 QueueMessage.MessageText 而不是对象本身解决了这个不需要的问题。绝对正确的观点,需要考虑! 【参考方案1】:队列模型的构造函数是内部的,但您可以使用QueuesModelFactory 创建对象,它提供了用于模拟的实用程序。
QueueMessage queueMsg = QueuesModelFactory.QueueMessage(
messageId: "id2",
popReceipt: "pr2",
body: JsonConvert.SerializeObject("Test"),
dequeueCount: 1,
insertedOn: DateTimeOffset.UtcNow);
var metadata = new Dictionary<string, string> "key", "value" , ;
int messageCount = 5;
QueueProperties queueProp = QueuesModelFactory.QueueProperties(metadata, messageCount);
【讨论】:
【参考方案2】:Mocking lib 的选择将是一个固执己见的答案。有几个可用的模拟框架。最受欢迎的之一是Moq。
使用最小起订量,您的上述代码的示例测试如下所示。请注意,如您所见,模拟存储库是一项有点乏味的任务。
[Test]
public async Task ReceiveMessagesAsync_StateUnderTest_ExpectedBehavior()
// Arrange
var queueClientHelper = new QueueClientHelper();
var queueMock = new Mock<QueueClient>();
var mockPropertiesResponse = new Mock<Response<QueueProperties>>();
var properties = new QueueProperties();
properties.GetType().GetProperty(nameof(properties.ApproximateMessagesCount), BindingFlags.Public | BindingFlags.Instance).SetValue(properties, 64); // little hack since ApproximateMessagesCount has internal setter
mockPropertiesResponse.SetupGet(r => r.Value).Returns(properties);
queueMock.Setup(q => q.GetProperties(It.IsAny<CancellationToken>())).Returns(mockPropertiesResponse.Object);
var mockMessageReponse = new Mock<Response<QueueMessage[]>>();
mockMessageReponse.SetupGet(m => m.Value).Returns(new QueueMessage[32]);
queueMock.Setup(q => q.ReceiveMessagesAsync(It.IsAny<int?>(), It.IsAny<TimeSpan?>(), It.IsAny<CancellationToken>())).ReturnsAsync(mockMessageReponse.Object);
// Act
var result = await queueClientHelper.ReceiveMessagesAsync(queueMock.Object);
// Assert
Assert.AreEqual(64, result.Length);
// verify mocks as required
【讨论】:
非常感谢!天哪【参考方案3】:尝试模拟 queueClient 的响应,这将验证 sendMessageAsync 响应
[Fact]
public async Task SendMessage_ShouldReturnSuccess()
var receipt = QueuesModelFactory.SendReceipt("1", DateTimeOffset.Now, DateTimeOffset.Now.AddDays(2), "pop", DateTimeOffset.Now.AddDays(1));
var res = Response.FromValue<SendReceipt>(receipt, null);
var queueClientmock = new Mock<QueueClient>();
queueClientmock.Setup(q => q.SendMessageAsync(It.IsAny<string>())).Returns(Task.FromResult(res));
var sqmock = new Mock<IStorageQueueProvider>();
sqmock.Setup(s => s.GetStorageQueueClient()).Returns(Task.FromResult(queueClientmock.Object)).Verifiable();
var storageQueueRepository = new StorageQueueRepository(sqmock.Object, DummyLogger);
var result = await storageQueueRepository.SendMessage("test message");
result.StatusCode.Should().Be(HttpStatusCode.OK);
【讨论】:
以上是关于如何模拟 Azure 队列存储以进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章
Vue,vuex:如何使用命名空间存储和模拟对组件进行单元测试?
如何模拟 mongodb 以进行单元测试 graphql 解析器