2011-04-12 13 views
9

Asumir: VS2010, .NET 4, C#, NUnit, Moqafirmación de una excepción lanzada desde un constructor de objetos mock

Soy nuevo en TDD y me encontré con este problema mientras se trabaja a través de un proyecto.

Teniendo en cuenta la clase:

public abstract class MyFileType 
{     
    public MyFileType(String fullPathToFile) 
    { 
     if (!File.Exists(fullPathToFile)) 
     { 
      throw new FileNotFoundException(); 
     } 

     // method continues 

    } 
} 

Estoy tratando de probarlo con el método:

[Test] 
[ExpectedException(typeof(System.IO.FileNotFoundException))] 
public void MyFileType_CreationWithNonexistingPath_ExceptionThrown() 
{ 
    String nonexistingPath = "C:\\does\\not\\exist\\file.ext"; 
    var mock = new Mock<MyFileType>(nonexistingPath); 
} 

La prueba falla y NUnit informa de una excepción nunca fue lanzada.

Encontré un section in the NUnit docs hablando de afirmar con excepciones, pero los ejemplos no parecían lo que estoy tratando de hacer. Todavía estoy comenzando con NUnit y Moq, así que puedo estar yendo por este camino equivocado.

ACTUALIZACIÓN:

para ayudar a aclarar por qué este ejemplo se utiliza una clase abstracta, que es la clase base de una serie de tipos de archivo en el que sólo la carga y la eliminación de los datos serían diferir entre tipos de subclases. Mi idea inicial fue poner la lógica para abrir/configurar en una clase base, ya que es la misma para todos los tipos.

+2

No estoy seguro de que esto está directamente relacionado con su problema, pero cambiando su definición de cadena a utilizar el '@ "" 'sintaxis es más fácil de leer y menos propenso a errores. Por ejemplo, en lugar de 'String nonexistingPath =" C: \\ does \\ not \\ exist \\ file.ext ";' puede simplemente poner 'String nonexistingPath = @" C: \ does \ not \ exist \ file \. ext ";' – Thebigcheeze

+0

Gracias por la sugerencia. He incorporado el cambio. – Noren

Respuesta

3

Si usted tiene que tener la clase uno abstracto, debemos entonces simplemente ponerlo en práctica, ya que está destinado a ser (simplicidad): MSDN: an abstract class

Así, acordando (con Alexanderb) que probablemente no se necesita un simulacro de aquí y también con Stecy en la extensión .Throws NUnit Assert, puede crear una clase en la prueba que llama a la clase base de la siguiente manera:

using System; 
using System.IO; 

namespace fileFotFoundException { 
    public abstract class MyFile { 

     protected MyFile(String fullPathToFile) { 
      if (!File.Exists(fullPathToFile)) throw new FileNotFoundException(); 
     } 
    } 
} 

namespace fileFotFoundExceptionTests { 
    using fileFotFoundException; 
    using NUnit.Framework; 

    public class SubClass : MyFile { 
     public SubClass(String fullPathToFile) : base(fullPathToFile) { 
      // If we have to have it as an abstract class... 
     } 
    } 

    [TestFixture] 
    public class MyFileTests { 

     [Test] 
     public void MyFile_CreationWithNonexistingPath_ExceptionThrown() { 
      const string nonExistingPath = "C:\\does\\not\\exist\\file.ext"; 

      Assert.Throws<FileNotFoundException>(() => new SubClass(nonExistingPath)); 
     } 
    } 
} 
+1

Estoy aceptando esta publicación como la respuesta ya que responde mi pregunta original. – Noren

2

Suponiendo que está utilizando la última versión de NUnit (debe), el atributo ExpectedException ha quedado obsoleto.

usted debe utilizar en su lugar el siguiente:

var exception = Assert.Throws<FileNotFoundException> (() => new MyFileType (nonExistingPath)); 
Assert.That (exception, Is.Not.Null); // Or you can check for exception text... 

No hay necesidad de utilizar un simulacro de allí. De hecho, el simulacro no hace nada interesante en su ejemplo.

+0

Estoy usando la última versión de NUnit, así que gracias por el aviso sobre la depreciación. Al probar su solución, encontré el mismo error que con la solución de alexanderb: no puedo crear una instancia de la clase abstracta 'MyFileType'. – Noren

2

Si intenta probar la clase MyFileType, arroja una excepción si el archivo no existe, por qué está creando simulacro. Usted código debe ser simple

[Test] 
[ExpectedException(typeof(System.IO.FileNotFoundException))] 
public void MyFileType_CreationWithNonexistingPath_ExceptionThrown() 
{ 
    // arrange 
    var nonexistingPath = "C:\\does\\not\\exist\\file.ext"; 

    // act/assert 
    var mock = new MyFileType(nonexistingPath); 
} 
+0

¿El hecho de que MyFileType no sea abstracto me impide usar el operador 'nuevo' como lo ha mostrado? – Noren

+0

opps, lo siento, me lo perdí. Claro, no puedes hacer 'nuevo' allí. Pero esto también significa que no debe probar directamente esta clase, ya que es abstracta. Tiene cierto comportamiento, pero este comportamiento debe probarse en clases heredadas de MyFileType. TDD, también podría apuntar a problemas de diseño. Si algo es difícil de probar, ese 99% es un error de diseño. En tu caso, si la clase es abstracta, es una mala idea poner la lógica en el constructor. –

5

el constructor no lo hará ser llamado hasta que referencia simulacro.Objeto. Eso debería desencadenar la excepción que estás esperando.

En una nota lateral, generalmente es una mala práctica que un constructor genere excepciones que no sean de uso (como los diversos derivados ArgumentException). La mayoría de los desarrolladores no esperan que 'nuevo' arroje una excepción a menos que lo hayan hecho algo muy mal; un archivo que no existe es el tipo de excepción que legítimamente puede suceder más allá del control del programa, por lo que es posible que desee convertirlo en un método de fábrica estático en lugar de "FromFileName". EDITAR: dado que este es un constructor de clase base, tampoco es realmente aplicable, por lo que es posible que desee considerar dónde es el mejor lugar para establecer este control. Después de todo, el archivo puede dejar de existir en cualquier momento, por lo que puede que ni siquiera tenga sentido verificar el constructor (deberá verificar todos los métodos relevantes de todos modos).)

+0

Acepto que mi intento inicial de este problema hizo que el código oliera a un constructor que hacía demasiado trabajo. – Noren

+0

+1 por no arrojar excepciones de un ctor. FxCop tiene una regla que marcará dicho código. – Pedro

3

Hoy enfrenté un problema similar. He trabajado a cabo utilizando la siguiente solución:

[Test] 
[ExpectedException(typeof(System.IO.FileNotFoundException))] 
public void MyFileType_CreationWithNonexistingPath_ExceptionThrown() 
{ 
    String nonexistingPath = "C:\\does\\not\\exist\\file.ext"; 
    var mock = new Mock<MyFileType>(nonexistingPath); 
    try 
    { 
     var target = mock.Object; 
    } 
    catch(TargetInvocationException e) 
    { 
     if (e.InnerException != null) 
     { 
      throw e.InnerException; 
     } 
     throw; 
    } 
} 
Cuestiones relacionadas