Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Duda al testear cambios en clase instanciada en un método con PHPUnit

20 de agosto de 2015

Buenas,

Estoy haciendo una aplicación y a la hora de escribir los tests con PHPUnit me he encontrado con que hay algunas cosas que no se como testear.

Tengo 2 entidades de doctrine Subscription y SubscriptionStateChange. La primera para guardar los datos de una suscripción y la segunda para guardar la hora de cualquier cambio de estado y a través de que partner llegó el cambio.

Luego tengo otra clase llamada SubscriptionManager donde agrupo algunas tareas como por ejemplo dar de baja una suscripción. El código de esta función es:

class SubscriptionManager
{
    public function unsubscribe(Subscription $subscription, Provider $partner = null)
    {
        $this->stateChange($subscription, Subscription::STATE_OPT_OUT, $partner);
    }
 
    private function stateChange(Subscription $subscription, $newState, Provider $partner = null)
    {
        $subscriptionStateChange = new SubscriptionStateChange(
            $subscription, $subscription->getState(), $newState
        );
 
        if ($partner !== null) {
            $subscriptionStateChange->setPartner($partner);
        }
 
        $subscription->setState($newState);
 
        $this->entityManager->persist($subscription);
        $this->entityManager->persist($subscriptionStateChange);
        $this->entityManager->flush();
    }
}

He podido testear que cambie al estado deseado creando un Mock del EntityManager de Doctrine.

Ahora me gustaría poder escribir un test para asegurarme de que en caso de pasarse un partner, se indica correctamente en la instancia de SubscriptionStateChange, pero al crearse dentro del método stateChange no puedo acceder a la instancia que se genera en el test. Estoy trabajando con PHPUnit por primera vez y no se si en este caso es que falta como hacerlo en PHPUnit, que intento testear algo innecesario, que eso no debería testearlo en PHPUnit o que hay un mal diseño del método unsubscribe.

Gracias


Respuestas

#1

Antes que nada, aclarar que no soy ningún experto en tets, así que mi respuesta es más una opinión personal derivada de mi propia experiencia. Yo diría que tienes tres posibles soluciones:

1) Simplificas el método stateChange() para que sólo cambie el estado (y acabe con un return $subscriptionStateChange) y después creas otro método para guardar las entidades en la base de datos. De esta manera te sería muy fácil testear que el método stateChange() hace los cambios que se le piden.

2) Haces un mock del EntityManager de Doctrine tal y como se explica en este artículo de la documentación de Symfony. En tu aplicación no tienes que cambiar nada, pero los tests se complican un poco. Además, en mi opinión, cuando en un test tienes mocks de todo, al final no estás testeando nada.

3) Usas una base de datos de verdad y dejas de que el método stateChange() haga los cambios en la base de datos y en el test simplemente compruebas el nuevo valor registrado en la base de datos. En Symfony esto es bastante fácil porque puedes configurar la base de datos de pruebas en app/config_test.yml. Lo malo es que hay mucha gente que considera una mala práctica hacer las consultas de verdad durante los tests y además, hará que la suite completa de test tarde más en ejecutarse.

@javiereguiluz

20 agosto 2015, 8:48
#2

Al final he optado por la primera opción, era la solución más simple y en 2 minutos ya estaba hecho.

Gracias por la ayuda ^^

@irozgar

21 agosto 2015, 8:23