Esperando una excepción en una prueba pero queriendo verificar la disposición se llama de todos modos

StackOverflow https://stackoverflow.com/questions/1617940

  •  06-07-2019
  •  | 
  •  

Pregunta

Estoy probando una aplicación de demostración, que es un cliente POP3. El cliente POP3 implementa IDisposable , así que estoy tratando de probar un ciclo usando .

(Estoy usando nunit 2.5.2 y 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();
}

Como puede ver, el método verifyAll nunca se invocará y la prueba tendrá éxito, no obstante. Entonces ...

  • ¿Cuál es la mejor manera de resolver esto?
  • ¿Hay otra manera de intentar atrapar?

Actualizar lo arreglé así por el momento:

        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);

Pero dispose no se llama , parece ser la especificación de C #.

¿Fue útil?

Solución

mockTcpClient.Setup(x => x.Dispose());

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

    }
}
finally 
{
    mockTcpClient.VerifyAll();
}

Otros consejos

Esto no responde a tu pregunta (como ya se resolvió), pero es relevante y vale la pena publicarla de todas formas.

[ExpectedException] es una forma bastante sencilla de probar las excepciones. Puede ser propenso a errores, ya que la línea incorrecta puede desencadenar una excepción del tipo esperado que resulta en un pase erróneo. Yo recomendaría encarecidamente que revises Assert.Throws () en su lugar :)

Es más fácil de usar (puede consultar la excepción devuelta), más legible y, sobre todo, más seguro.

Puede encontrar un ejemplo aquí

Ya has descubierto que se supone que disperse realmente no si el constructor falla. Pero aún puede haber otros casos en los que desee verificar sus simulacros después de que se lance una excepción esperada. Solo hago eso en la prueba TearDown de esta manera:

[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();
}

Parece que está probando que la instancia de mockTcpClient inyectada está dispuesta incluso si el constructor lanza una excepción, en cuyo caso esto debería funcionar:

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

EDITAR: En realidad, intentar / finalmente sería más limpio que atrapar Excepción. Tenga en cuenta que no necesita desechar popClient ya que no se crea ninguna instancia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top