2011-07-26 12 views
6

Esta es la situación. Tuve una llamada asíncrona, así que tuve que hacer un nivel medio para esto para poder probarlo.Defina la implementación del método en el objeto simulado usando Moq

request.BeginGetResponse(new AsyncCallback(LoginCallback), requestState); 

Entonces, para poder probar esto sin una solicitud real, creé una interfaz que puedo simular.

public interface IRequestSender 
    { 
     void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState); 
    } 

Luego, en la ejecución que puede utilizar la llamada de esa manera uno por encima y me puede proporcionar una cierta clase de simulacro para llamar a mi método de devolución de llamada, independientemente solicitud es válida o no. Mi clase simulada se ve así.

public class RequestSenderMock : IRequestSender 
    { 
     public void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState) 
     { 
      var result = new Mock<IAsyncResult>(); 
      result.Setup(x => x.AsyncState).Returns(requestState); 
      internalCallback(result.Object); 
     } 
    } 

ahora puedo crear fácilmente objeto de burla en mi prueba de la unidad y utilizarla. Pero cuando creo

var sender = new Mock<RequestSenderMock>(); 

No puedo verificar el conteo de llamadas para este objeto.

sender.Verify(x => x.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>()), Times.Once()); 

Dice que mi método debe ser virtual. ¿Hay alguna manera de hacerlo sin hacer que mi método sea virtual? Sería mejor si de alguna manera pudiera especificar la impelementación del método al usar la interfaz.

var sender = new Mock<IRequestSender>(); 

Y eso de alguna manera con el método de instalación o algún otro para hacer la implementación en este objeto simulacro. Entonces simplemente eliminaré mi clase simulada. ¿Esto es posible? ¿Que sugieres?

Respuesta

8

Me resulta confuso crear un simulacro manual y utilizar un marco de burla para burlarse de él (burlarse de un simulacro). Consideraría mover sus funciones personalizadas a alguna clase de utilidad y usar devoluciones de llamadas.

Ejemplo:

public class RequestSenderHelpers 
{ 
    public static void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState) 
    { 
     var result = new Mock<IAsyncResult>(); 
     result.Setup(x => x.AsyncState).Returns(requestState); 
     internalCallback(result.Object); 
    } 

} 

    [Test] 
    public void Callback_VerifyingWithMethodImplementation_VerifyWorks() 
    { 
     // arrange 
     var sender = new Mock<IRequestSender>(); 
     sender.Setup(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())).Callback<HttpWebRequest, AsyncCallback, object>(RequestSenderHelpers.Send); 

     // act 
     sender.Object.Send(null, delegate {}, null); 

     // assert 
     sender.Verify(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())); 
    } 

Para evitar la configuración detallada se puede envolver la configuración del método en un método de extensión y cambiar su prueba en consecuencia:

public static class RequestSenderHelpers 
{ 
    public static void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState) 
    { 
     var result = new Mock<IAsyncResult>(); 
     result.Setup(x => x.AsyncState).Returns(requestState); 
     internalCallback(result.Object); 
    } 

    public static void SetupSendWithMockedAsyncResult(this Mock<IRequestSender> sender) 
    { 
     sender.Setup(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())).Callback<HttpWebRequest, AsyncCallback, object>(Send);    
    } 

} 

    [Test] 
    public void Callback_VerifyingWithMethodImplementation_VerifyWorks() 
    { 
     // arrange 
     var sender = new Mock<IRequestSender>(); 
     sender.SetupSendWithMockedAsyncResult(); 

     // act 
     sender.Object.Send(null, delegate {}, null); 

     // assert 
     sender.Verify(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())); 
    } 
+0

Gracias, eso es exactamente lo que necesitaba. :) – Vajda

Cuestiones relacionadas