Pregunta

¿Tengo que volver a escribir mi código para hacer esto en una interfaz? ¿O hay una forma más fácil? Estoy usando Moq

¿Fue útil?

Solución

Lo que normalmente hago es crear un contenedor o un adaptador alrededor de mi servicio web y simplemente burlarme de eso.

por ejemplo:

public class ServiceAdapter: IServiceAdapter
{
    public void CallSomeWebMethod()
    {
        var someService = new MyWebService();
        someService.SomeWebMethod();
    }
}

Luego solo aplasto el adaptador de servicio.

[Test]    
public void SomeMethod_Scenario_ExpectedResult()
{
    var adapterMock = new Mock<IServiceAdapter>();
    //do your test
}

Otros consejos

he estado escribiendo un par de respuestas acerca de las pruebas de unidad y la burla últimamente. Escribí en otra parte que es importante preguntarse qué exactamente está probando. Con respecto a su situación particular, espero que la respuesta sea "Estoy probando la lógica de negocios que mi Servicio Web está exponiendo", y no "Estoy probando mi Servicio Web". - Hay una diferencia.


Si sus preocupaciones son server-side

No es necesario probar WebServices en general. MS ya lo ha hecho. Millones de personas lo han hecho. Probar la capa de transporte, el protocolo, la definición de servicios web es una pérdida de tiempo.

Debe orientar su lógica de negocios . La mejor manera de hacer esto es separar su lógica de negocios de su servicio web. Considera lo siguiente

public class MyWebSevice : System.Web.Services.WebService
{
    private AuthenticationService _auth = new AuthenticationService ();
    private int _count = 0;
    [WebMethod]
    public string DoSomething ()
    {
        // embedded business logic, bad bad bad
        if (_auth.Authenticate ())
        {
            _count++;
        }
        return count.ToString ();
    }
}

no hay forma de probar esa lógica sin invocar el servicio web directamente. Lo que realmente quieres es

public class MyService 
{
    // keeners will realise this too should be injected
    // as a dependency, but just cut and pasted to demonstrate
    // isolation
    private AuthenticationService _auth = new AuthenticationService ();
    private int _count = 0;
    public string DoSomething ()
    {
        if (_auth.Authenticate ())
        {
            _count++;
        }
        return count.ToString ();
    }
}

en prod

// this web service is now a consumer of a business class,
// no embedded logic, so does not require direct testing
public class MyWebSevice : System.Web.Services.WebService
{
    private readonly MyService _service = new MyService ();

    [WebMethod]
    public string DoSomething ()
    {
        _service.DoSomething ();
    }
}

en prueba

// test business logic without web service! yay!
[Test]
public void Test_DoSomething ()
{
    MyService service = new MyService ();
    string actual = service.DoSomething ();
    // verify results
}

administrar dependencias [como el miembro de AuthenticationService] es un problema aparte. Sin embargo, hacer que sus Pasajes a través de WebMethods sean sencillos a las clases de negocios subyacentes adecuadas y eliminar la lógica de ellos por completo, le permite orientar " real " código de usuario en lugar de la instalación de su implementación típica de servicio web.


Si sus preocupaciones son cliente- lado

Usted tiene un componente empresarial que llama un servicio web, y estoy de acuerdo en que no desea crear un cliente para pruebas de unidad.

public partial class MyWebService :
    System.Web.Services.Protocols.SoapHttpClientProtocol 
{
    ...
    public string DoSomething () { ... }
}

public class MyClient
{
    public void CallService ()
    {
        MyWebService client = new MyWebService ();
        client.DoSomething ();
    }
}

Aquí, tiene problemas de dependencia, es decir, no puede probar MyClient.CallService sin crear una instancia y alojar su servicio web. Especialmente desconcertante si no es propietario o anfitrión de dicho servicio remoto. En este caso, sí, debe escribir en contra de una interfaz, una vez más para separar y aislar la lógica empresarial.

public interface IMyWebService
{
    string DoSomething ();
}

public class MyWebServiceWrapper : IMyWebService
{
    public string DoSomething () 
    {
        MyWebService client = new MyWebService ();
        client.DoSomething ();
    }
}

public class MyClient
{
    private readonly IMyWebService _client = null;
    public MyClient () : this (new MyWebServiceWrapper ()) { }
    public MyClient (IMyWebService client)
    {
        _client = client;
    }
    public void CallService ()
    {
        _client.DoSomething ();
    }
}

en prueba

[Test]
public void Test_CallService ()
{
    IMyWebService mockService = null;
    // instantiate mock with expectations
    MyClient client = new MyClient (mockService);
    client.CallService ();
    // verify results
}

En general, si las dependencias de una clase son servicios en proceso, la decisión de aplicar un patrón como la inyección de dependencia [DI] o la Inversión de control [IoC] depende de usted, y su deseo de aislar y probar estos servicios por unidad. Informará a su diseño. Sin embargo, si las dependencias de una clase cruzan un límite de proceso , por ejemplo, Database o WebService, recomiendo aplicar estos patrones como hicimos anteriormente.

En realidad, es simplemente el desarrollo de una interfaz antigua. Probablemente ya veas cómo vale la pena.

:)

I blogged sobre esto hace mucho tiempo. Básicamente, utilizando clases parciales y un poco de esfuerzo (ya sea automatizado o manual, dependiendo de la frecuencia con la que vaya a cambiar el servicio web), puede hacer que la clase proxy del servicio web implemente una interfaz. A continuación, puede burlarse de él como de costumbre.

hay una manera fácil. por ejemplo, si tenemos una clase de Servicio Web con el nombre DbService, primero cree una interfaz para ella (por ejemplo, IService), y use esta interfaz para burlarse, luego agregue una clase a su proyecto y ponga esto:

public partial class DbService:IService {

}

deje la clase en blanco, ya que los servicios web son de clase parcial, usamos esta implementación. (anteriormente

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