usuario tipos que propias por personalizar personalizadas manejo lanzar existen excepciones errores crear creadas como capturar c# unit-testing mocking moq

propias - que tipos de excepciones existen en c#



¿Se burla de un método para lanzar una excepción(moq), pero actúa como el objeto burlado? (3)

Tengo una clase de Transfer , simplificado, se ve así:

public class Transfer { public virtual IFileConnection source { get; set; } public virtual IFileConnection destination { get; set; } public virtual void GetFile(IFileConnection connection, string remoteFilename, string localFilename) { connection.Get(remoteFilename, localFilename); } public virtual void PutFile(IFileConnection connection, string localFilename, string remoteFilename) { connection.Get(remoteFilename, localFilename); } public virtual void TransferFiles(string sourceName, string destName) { source = internalConfig.GetFileConnection("source"); destination = internalConfig.GetFileConnection("destination"); var tempName = Path.GetTempFileName(); GetFile(source, sourceName, tempName); PutFile(destination, tempName, destName); } }

La versión simplificada de la interfaz IFileConnection tiene este aspecto:

public interface IFileConnection { void Get(string remoteFileName, string localFileName); void Put(string localFileName, string remoteFileName); }

Se supone que la clase real maneja una System.IO.IOException que se lanza cuando las clases concretas de IFileConnection pierden conectividad con el control remoto, el envío de correos electrónicos y otras IFileConnection .

Me gustaría usar Moq para crear una clase de Transfer , y usarla como mi clase de Transfer concreta en todas las propiedades y métodos, excepto cuando se invoca el método GetFile - entonces quiero que arroje una System.IO.IOException y asegúrese de que Transfer clase de Transfer maneja correctamente.

¿Estoy usando la herramienta correcta para el trabajo? ¿Voy por esto de la manera correcta? ¿Y cómo escribiría la configuración para esa prueba unitaria para NUnit ?


Así es como logré hacer lo que estaba tratando de hacer:

[Test] public void TransferHandlesDisconnect() { // ... set up config here var methodTester = new Mock<Transfer>(configInfo); methodTester.CallBase = true; methodTester .Setup(m => m.GetFile( It.IsAny<IFileConnection>(), It.IsAny<string>(), It.IsAny<string>() )) .Throws<System.IO.IOException>(); methodTester.Object.TransferFiles("foo1", "foo2"); Assert.IsTrue(methodTester.Object.Status == TransferStatus.TransferInterrupted); }

Si hay un problema con este método, me gustaría saber; las otras respuestas sugieren que estoy haciendo esto mal, pero esto era exactamente lo que estaba tratando de hacer.


Así es como puedes FileConnection tu FileConnection

Mock<IFileConnection> fileConnection = new Mock<IFileConnection>( MockBehavior.Strict); fileConnection.Setup(item => item.Get(It.IsAny<string>,It.IsAny<string>)) .Throws(new IOException());

A continuación, crea una instancia de tu clase de transferencia y utiliza el simulacro en tu llamada al método

Transfer transfer = new Transfer(); transfer.GetFile(fileConnection.Object, someRemoteFilename, someLocalFileName);

Actualizar:

En primer lugar, tiene que burlarse de sus dependencias solamente, no de la clase que está probando (Clase de transferencia en este caso). Al indicar esas dependencias en su constructor, es más fácil ver qué servicios necesita su clase para funcionar. También hace posible reemplazarlos con falsificaciones cuando está escribiendo las pruebas de su unidad. Por el momento, es imposible reemplazar esas propiedades con falsificaciones.

Como está configurando esas propiedades usando otra dependencia, lo escribiría así:

public class Transfer { public Transfer(IInternalConfig internalConfig) { source = internalConfig.GetFileConnection("source"); destination = internalConfig.GetFileConnection("destination"); } //you should consider making these private or protected fields public virtual IFileConnection source { get; set; } public virtual IFileConnection destination { get; set; } public virtual void GetFile(IFileConnection connection, string remoteFilename, string localFilename) { connection.Get(remoteFilename, localFilename); } public virtual void PutFile(IFileConnection connection, string localFilename, string remoteFilename) { connection.Get(remoteFilename, localFilename); } public virtual void TransferFiles(string sourceName, string destName) { var tempName = Path.GetTempFileName(); GetFile(source, sourceName, tempName); PutFile(destination, tempName, destName); } }

De esta forma puede burlarse de InternalConfig y hacer que regrese. IFileConnection se burla de que hace lo que quiere.


Creo que esto es lo que quieres, ya probé este código y funciona

Las herramientas utilizadas son: (todas estas herramientas se pueden descargar como paquetes de Nuget)

http://fluentassertions.codeplex.com/

http://autofixture.codeplex.com/

http://code.google.com/p/moq/

https://nuget.org/packages/AutoFixture.AutoMoq

var fixture = new Fixture().Customize(new AutoMoqCustomization()); var myInterface = fixture.Freeze<Mock<IFileConnection>>(); var sut = fixture.CreateAnonymous<Transfer>(); myInterface.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>())) .Throws<System.IO.IOException>(); sut.Invoking(x => x.TransferFiles( myInterface.Object, It.IsAny<string>(), It.IsAny<string>() )) .ShouldThrow<System.IO.IOException>();

Editado:

Dejame explicar:

Cuando escribe una prueba, debe saber exactamente qué quiere probar, esto se llama: "sujeto bajo prueba (SUT)", si mi entendimiento es correcto, en este caso su SUT es: Transfer

Entonces, con esto en mente, no deberías burlarte de tu SUT, si sustituyes tu SUT, entonces no estarías realmente probando el código real.

Cuando su SUT tiene dependencias externas (muy comunes), debe sustituirlas para probar aisladamente su SUT. Cuando digo sustituto me refiero a usar un simulacro, simulado, simulacro, etc. según sus necesidades

En este caso, su dependencia externa es IFileConnection por lo que necesita crear un simulacro para esta dependencia y configurarlo para lanzar la excepción, luego solo llame a su método SUT real y afirme que su método maneja la excepción como se esperaba

  • var fixture = new Fixture().Customize(new AutoMoqCustomization()); : Este linie inicializa un nuevo objeto Fixture (biblioteca Autofixture), este objeto se usa para crear SUT sin tener que preocuparse explícitamente por los parámetros del constructor, ya que se crean automáticamente o se burlan, en este caso usando Moq

  • var myInterface = fixture.Freeze<Mock<IFileConnection>>(); : Esto congela la dependencia IFileConnection . Congelar significa que Autofixture usará siempre esta dependencia cuando se le pida, como un singleton por simplicidad. Pero la parte interesante es que estamos creando un simulacro de esta dependencia, puedes usar todos los métodos Moq, ya que este es un simple objeto Moq

  • var sut = fixture.CreateAnonymous<Transfer>(); : Aquí AutoFixture está creando el SUT para nosotros

  • myInterface.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>())).Throws<System.IO.IOException>(); Aquí está configurando la dependencia para lanzar una excepción cada vez que se llama al método Get , el resto de los métodos de esta interfaz no se están configurando, por lo tanto, si intenta acceder a ellos, obtendrá una excepción inesperada

  • sut.Invoking(x => x.TransferFiles(myInterface.Object, It.IsAny<string>(), It.IsAny<string>())).ShouldThrow<System.IO.IOException>(); : Y finalmente, el tiempo para probar su SUT, esta línea usa la biblioteca FluenAsertions, y solo llama al método real TransferFiles del SUT y como parámetros recibe el IFileConnection así que siempre que llame al IFileConnection.Get en el flujo normal de su método SUT TransferFiles , el objeto burlado invocará lanzando la excepción configurada y este es el momento de afirmar que su SUT maneja correctamente la excepción, en este caso, solo estoy asegurando que la excepción fue lanzada usando el sistema ShouldThrow<System.IO.IOException>() (de la biblioteca FluentAsertions)

Referencias recomendadas:

http://martinfowler.com/articles/mocksArentStubs.html

http://misko.hevery.com/code-reviewers-guide/

http://misko.hevery.com/presentations/

http://www.youtube.com/watch?v=wEhu57pih5w&feature=player_embedded

http://www.youtube.com/watch?v=RlfLCWKxHJ0&feature=player_embedded