首页 > 解决方案 > Moq 验证特定异常是否被抛出并被捕获

问题描述

如有必要,我有一种创建队列的方法。如果队列已经存在,则该方法返回 false,如果创建成功则返回 true。

我想测试在QueueExists检查期间队列不存在但在调用之前由另一个进程创建的场景CreateQueueAsync

我有我的产品代码:

internal bool QueueExists(string queueName)
{
    var allQueues = ManagementClient.GetQueuesAsync().Result;
    if (!allQueues.Any(q => q.Path.Equals(queueName)))
    {
        return false;
    }
    return true;
}
public bool CreateQueueIfNotExists(string queueName, bool requiresSession)
{
    if (!QueueExists(queueName))
    {
        try
        {
            ManagementClient.CreateQueueAsync(queueDescription).Wait();
            return true;
        }
        catch (AggregateException ae)
        {
            Exception e = ae.GetBaseException();

            // If the queue already exists then no additional action is needed.
            if (e is MessagingEntityAlreadyExistsException)
            {
                return false;
            }
            else
            {
                ExceptionDispatchInfo.Throw(e);
            }
        }
    }
    else
    {
        return false;
    }
}

我的 Nunit 测试CreateQueueAsync将被调用两次,因为它GetQueuesAsync总是返回一个空列表。

[Test]
public void QueueCreation_MessagingEntityAlreadyExistsException_IsCatched()
{
    // Given            
    var managementClientMock = new Mock<ManagementClient>(connectionString) { CallBase = true };
    managementClientMock.Setup(m => m.GetQueuesAsync(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<System.Threading.CancellationToken>()))
        .Returns(Task.FromResult<IList<QueueDescription>>(new List<QueueDescription>()));
    QueueFactory queueFactory = new QueueFactory(managementClientMock.Object);

    Assert.That(queueFactory.CreateQueueIfNotExists(alreadyExistsQueue, true), Is.True, 
"First queue creation did not returned true.");
    Assert.That(queueFactory.CreateQueueIfNotExists(alreadyExistsQueue, true), Is.False, 
"First queue creation did not returned false.");
    managementClientMock.Verify(m => m.CreateQueueAsync(It.IsAny<QueueDescription>(), It.IsAny<System.Threading.CancellationToken>()), Times.Exactly(2));
}

这很好,但是我想检查是否第二次抛出并捕获了聚合异常并且MessagingEntityAlreadyExistsException是内部异常。所以ExpectedExceptionandAssert.Throws在这里不起作用,在 product 方法中捕获了异常。

我有办法用 Moq 做到这一点吗?

标签: c#nunitmoq

解决方案


有趣的问题 - 我不知道起订量中有任何这样做的东西。但是,您是否能够通过将问题一分为二来获得所需的内容(如果我误解了,请道歉)?

首先,单独测试ManagementClient,验证在同一个队列中调用两次会引发聚合异常,也MessagingEntityAlreadyExistsException就是内部异常。

其次,使用存根 ManagementClient 测试属于您示例中的方法的代码,该存根 ManagementClient 在调用时会引发包含相同内部异常的聚合异常。在那个测试中,验证没有抛出异常(即异常被捕获并且没有重新抛出)。


推荐阅读