Pregunta

Quiero probar un fragmento de código que usa la red (la clase NSURLConnection , para ser específica). El código (llamémoslo NetworkManager ) es un poco así:

- (id) buildConnection
{
    // some more code and then:
    return [NSURLConnection …];
}

- (void) startNetworkSync
{
    id connection = [self buildConnection];
    //…
}

En la prueba de la unidad me gustaría deshacerme de la red, es decir. reemplaza el objeto NSURLConnection por un simulacro. ¿Cómo hago esto?

He intentado crear una simulación parcial del NetworkManager que reemplazaría el método buildConnection por un código auxiliar. El problema es que los simulacros parciales realizados por OCMock solo envían mensajes del resto del mundo & # 8211; El envío de buildConnection desde startNetworkSync invoca el método original, no el código auxiliar.

También he intentado parchear a la clase NetworkManager a través de una categoría. Esto funciona, puedo anular fácilmente el método buildConnection por otro código y reemplazar el NSURLConnection real con un código auxiliar. El problema es que no encontré una forma sencilla de obtener la conexión aplastada en la prueba & # 8211; la conexión es una parte privada del NetworkManager .

Luego podría subclasificar el NetworkManager , anular el método buildConnection y agregar una variable de instancia más un elemento de acceso para la conexión creada. Sin embargo, esto parece mucho código.

¿Cómo resolverías esto? Estoy buscando una solución que mantenga limpio el diseño de la clase NetworkManager y que no requiera mucha magia ni mucho código en la prueba.

¿Fue útil?

Solución

Este es el tipo de cosa que la inyección de dependencia está diseñada para resolver; Si usa startNetworkSyncWithConnection: (NSURLConnection *) , puede probar el método fácilmente con una conexión simulada. Si no desea cambiar la API para sus clientes, incluso podría mantener startNetworkSync como un contenedor que no hace más que llamar a ese nuevo método con [self buildConnection] como argumento.

Otros consejos

He modificado OCMock para que sea compatible con simulacros parciales reales, consulte repo en GitHub .

Otra solución que he usado recientemente es abstraer completamente la interfaz de red. Si la clase necesita algunos datos de la red, probablemente interactúe con algún servicio del servidor que pueda modelarse explícitamente como un protocolo:

@protocol SomeNetworkService
- (NSArray*) allAvailableFoos;
- (void) insertNewFoo: (Foo*) foo;
@end

Y luego, tendrás una implementación HTTP real y una de prueba. Esto significa más trabajo, pero también una mejor capacidad de prueba. Las pruebas son menos frágiles y mucho más convenientes, ya que la capa de red de pruebas puede hacer lo que sea necesario.

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