2011-11-26 22 views
7

Tengo un comportamiento extraño en una prueba en la que deseo probar que se lanza una excepción cuando se pasa nulo como parámetro. Cuando ejecuto la prueba que recibo de NUnit:Comportamiento extraño con NUnit, ExpectedException y yield return

System.ArgumentNullException was expected 
    -- Exception doesn't have a stack trace -- 

Mi prueba:

[Test] 
[ExpectedException(typeof(ArgumentNullException))] 
public void Should_not_retrieve_any_fields_when_file_is_null() 
{ 
    _creator.CreateFields(null); 
} 

Mi aplicación:

public IEnumerable<ImportField> CreateFields(HttpPostedFileBase file) 
{ 
    if (file == null) throw new ArgumentNullException("file"); 

    using (var reader = new StreamReader(file.InputStream)) 
    { 
     var firstLine = reader.ReadLine(); 
     var columns = firstLine.Split(new[] { ',' }); 

     for (var i = 0; i < columns.Length; i++) 
     { 
      yield return new ImportField(columns[i], i); 
     } 
    } 
} 

¿Hay una explicación lógica a este comportamiento y debo hacer mi implementación de manera diferente?

Respuesta

7

La razón por la que está obteniendo este comportamiento es debido a la palabra clave yield. Al usar el rendimiento, el compilador generará una clase para el método con el rendimiento en él. Al llamar a ese método, el control se devuelve incondicionalmente a la persona que llama. Nada en su método se ejecuta realmente antes de que sea necesario.

Si extrae su declaración de uso en un método diferente y devuelve el resultado, su prueba se aprobará. O puede almacenar el resultado en una variable en su prueba y, por ejemplo, llamar a "ToList()" en él.

public IEnumerable<ImportField> CreateFields(HttpPostedFileBase file) 
    { 
     if (file == null) throw new ArgumentNullException("file"); 

     return ExtractFromFile(file); 
    } 

    private IEnumerable<ImportField> ExtractFromFile(HttpPostedFileBase file) 
    { 
     using (var reader = new StreamReader(file.InputStream)) 
     { 
      var firstLine = reader.ReadLine(); 
      var columns = firstLine.Split(new[] { ',' }); 

      for (var i = 0; i < columns.Length; i++) 
      { 
       yield return new ImportField(columns[i], i); 
      } 
     } 
    } 
+0

+1 nice catch !! – sll