В любом случае вызывается ожидание исключения в тесте, но желание проверить удаление

2

Я тестирую демо-приложение, которое является клиентом POP3. Клиент POP3 реализует IDisposable, поэтому я пытаюсь проверить цикл using.

(Я использую nunit 2.5.2 и Moq 4.0)

/// <summary>
/// Unsuccessful construct dispose cycle, no ILogger object given. 
/// Expecting ArgumentNullException. Expecting TcpClient dispose to be called.
/// </summary>
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void ConstructorDispose_LoggerNull_ArgumentNullException()
{
    mockTcpClient.Setup(x => x.Dispose());
    using (var popClient = new PopClient(null, mockTcpClient.Object))
    {

    }
    mockTcpClient.VerifyAll();
}

Как вы можете видеть, метод verifyAll никогда не будет вызываться, и тест будет успешным, тем не менее. Итак...

  • Каков наилучший способ решить эту проблему?
  • Есть ли другой способ, а затем попытаться поймать?

Обновление. Я исправил его так:

        mockTcpClient.Setup(x => x.Dispose());
        var correctExceptionThrown = false;
        try
        {
            using (var popClient = new PopClient(null, mockTcpClient.Object))
            {

            }
        }
        catch (ArgumentNullException)
        {
            correctExceptionThrown = true;
        }
        finally
        {
            mockTcpClient.VerifyAll();
        }
        Assert.That(correctExceptionThrown);

Но dispose не называется, кажется, является спецификацией С#.

  • 1
    Утилизация PopClient не будет вызвана, если его конструктор не удастся. Но в этом случае конструктор должен распорядиться ресурсами, которыми он владеет, прежде чем распространять исключения.
Теги:
unit-testing
moq
nunit

4 ответа

3
Лучший ответ
mockTcpClient.Setup(x => x.Dispose());

try 
{
    using (var popClient = new PopClient(null, mockTcpClient.Object))
    {

    }
}
finally 
{
    mockTcpClient.VerifyAll();
}
  • 0
    Вы должны убедиться, что это выбрасывает правильное исключение.
2

Это не отвечает на ваш вопрос (как он уже решил), но он все равно стоит и стоит публиковать.

[ExpectedException] - довольно верный способ проверить исключения. Он может быть подвержен ошибкам, поскольку неправильная строка может инициировать исключение ожидаемого типа, что приводит к ошибочному проходу. Я бы настоятельно рекомендовал вам проверить Assert.Throws() вместо:)

Лучше использовать (вы можете запросить возвращаемое исключение), более читаемым и, прежде всего, более безопасным.

Здесь вы можете найти пример

2

Вы уже обнаружили, что на самом деле dispose действительно not, если конструктор терпит неудачу. Но могут быть и другие случаи, когда вы можете проверить свои mocks после того, как будет выбрано ожидаемое исключение. Я просто делаю это в тесте TearDown следующим образом:

[SetUp]
public void SetUp()
{
   this.mockFactory = new MockFactory(MockBehavior.Loose);
}

[TearDown]
public void TearDown()
{
   this.mockFactory.VerifyAll();
}


[Test]
[ExpectedException(typeof(NoBananasException))]
public void EatThrowsIfNoBananasAvailable
{
   var bananaProvider = this.mockFactory.Create<IBananaProvider>();
   bananaProvider.SetUp(bp => bp.IsBananaAvailable).Returns(false).Verifiable();

   var monkey = new Monkey(bananaProvider.Object);
   monkey.Eat();
}
1

Кажется, вы тестируете, что инъецированный экземпляр mockTcpClient удаляется, даже если конструктор генерирует исключение, и в этом случае это должно работать:

mockTcpClient.Setup(x => x.Dispose());
try
{
    var popClient= new PopClient(null, mockTcpClient.Object);
}
finally
{
    mockTcpClient.VerifyAll();
}

РЕДАКТИРОВАТЬ: Вообще-то, попробуйте/наконец-то станет чище, чем поймать Исключение. Обратите внимание, что вам не нужно удалять popClient, поскольку не создается экземпляр.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню