Symfony : Mock LDAP Componente en pruebas funcionales

Quiero hacer pruebas funcionales en mi aplicación Symfony (5.1), esta aplicación utiliza un servidor Active Directory como una base de datos "datas" (crear, enumerar, actualizar datos). Estoy usando el componente Symfony ldap. El ejemplo del código puede contener los tipos.

Controlador

class DatasController
{
/**
     * @Route("/datas", name="datas")
     * @IsGranted("ROLE_USER")
     *
     * @return Response
     * @desc Displays LDAP datas
     */
    public function datasList(DatasRepository $datasRepository)
    {
        $datas = $datasRepository->findAll();
        return $this->render('datas/list.html.twig', [
            'datas' => $datas,
        ]);
    }
}

Repositorio

class DatasRepository
{
    private Ldap $ldap;
    private EntryManagerInterface $manager;

    /**
     * DatasRepository constructor.
     * Service injected params
     */
    public function __construct(Ldap $ldap, string $ldapAdminLogin, string $ldapAdminPwd)
    {
        $this->ldap = $ldap->bind($ldapAdminLogin, $ldapAdminPwd);
        $this->manager = $ldap->getEntryManager();
    }
    
    public function create(Data $data): void
    {
        // ... some $data to Symfony\Component\Ldap\Entry $entry logic
        
        $this->manager->add( $entry );
    }

    /**
     * @return datas[]
     */
    public function findAll()
    {
        $this->ldap->query('ou=test', '(&(objectclass=person))');
        $entries = $query->execute()->toArray();

        // ... some $entries to $datas logic

        return $datas;
    }
    
}

Prueba

class DatasControllerTest extends WebTestCase
{
    public function testDatasList()
    {
        $client = static::createClient();
        $client->request('GET', '/datas');
        # Crash can't contact LDAP and thats logical
        $this->assertResponseIsSuccessful();
    }
}

Entonces, ¿cómo hacer la prueba funcional en "GET /datas" ? ¿Qué parte del código debería burlarme para maximizar la eficiencia y cobertura de la prueba?

Algunas informaciones adicionales:

  • No puedo tener un servidor LDAP dedicado para pruebas (las pruebas se ejecutan bajo Docker vía gitlab-ci)
  • Soy consciente del "no te burles de lo que no propio".
  • He leído muchos artículos/artículos diciendo "debes burlarte de la LdapAdapter" pero no tengo ni idea de cómo lograr esto y no encontró cualquier ejemplo.

Cualquier sugerencia es bienvenida. Gracias.

Eric

Pregunta hecha hace 3 años, 5 meses, 0 días - Por binaryblossom


3 Respuestas:

  • Acerca de mockin servicios externos: puede ampliar el servicio de prueba desde el original y hacer que los métodos se comportan como usted desea. Ex.:

    class TestService extends \Symfony\OrAnyOtherExternalService
    {
        public function getConnection()
        {
            return new Connection([]);
        }
    }
    

    entonces en su prueba de servicios. Yaml cambiar la clase de este servicio a usted prueba servicio:

    services:
        Symfony\OrAnyOtherExternalService:
            class: TestData\Services\TestService
    

    de esta manera en la aplicación del entorno de prueba utilizará TestService en lugar de original

    Respondida el Dec 17, 2020 a las 13:21 - por codecrusaderx

    Votos positivos: 0 | Votos negativos: 0

  • Para realizar pruebas unitarias en Symfony cuando se depende de un servicio externo como LDAP, lo recomendable es usar mocks para simular el comportamiento del servicio y evitar depender de la conexión real con el servidor LDAP.

    En tu caso, puedes crear un mock del servicio LDAP y configurarlo para que devuelva los resultados esperados en tus pruebas. Symfony recomienda utilizar el componente MockBuilder para crear mocks fácilmente. Aquí tienes un ejemplo de cómo podrías hacerlo en tu clase de prueba:

    php
    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    use Symfony\Component\Ldap\Ldap;
    use Symfony\Component\Ldap\EntryManager;
    
    class DatasControllerTest extends WebTestCase
    {
        public function testDatasList()
        {
            // Crear un mock del servicio LDAP
            $ldapMock = $this->getMockBuilder(Ldap::class)
                   
    • >disableOriginalConstructor()
    • >getMock();
    // Configurar el mock para devolver resultados esperados $ldapMock->method('query')
    • >willReturn(/ Devolver tu respuesta esperada aquí /);
    $ldapMock->method('getEntryManager')
    • >willReturn(new EntryManager($ldapMock));
    // Crear una instancia del controlador con el mock del servicio LDAP $datasRepository = new DatasRepository($ldapMock, / ldapAdminLogin /, / ldapAdminPwd /); $client = static::createClient(); $client->request('GET', '/datas'); $this->assertResponseIsSuccessful(); } }

    Puedes llenar los métodos willReturn con los valores que esperas obtener al llamar a esas funciones. De esta manera, podrás simular el comportamiento del servidor LDAP sin necesitar una conexión real durante tus pruebas.

    Espero que esta sugerencia te ayude a maximizar la eficiencia y cobertura de tus pruebas funcionales. ¡Buena suerte con tus pruebas!

    Respondida el Dec 18, 2020 a las 13:23 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Burla de la clase Ldap

    Para burlarte de la clase Ldap, puedes usar el marco de pruebas PHPUnit. Aquí tienes un ejemplo:

    php
    use PHPUnit\Framework\TestCase;
    use Symfony\Component\Ldap\Ldap;
    use Symfony\Component\Ldap\EntryManagerInterface;
    
    class DatasControllerTest extends TestCase
    {
        /*
          @var Ldap|\PHPUnit_Framework_MockObject_MockObject
         /
        private $ldapMock;
    
        /
          @var EntryManagerInterface|\PHPUnit_Framework_MockObject_MockObject
         /
        private $entryManagerMock;
    
        public function setUp()
        {
            $this->ldapMock = $this->createMock(Ldap::class);
            $this->entryManagerMock = $this->createMock(EntryManagerInterface::class);
        }
    
        public function testDatasList()
        {
            $client = static::createClient();
    
            // Configura las expectativas del mock de LDAP
            $this->ldapMock->expects($this->once())
                   
    • >method('bind')
    • >willReturn($this->ldapMock);
    $this->ldapMock->expects($this->once())
    • >method('getEntryManager')
    • >willReturn($this->entryManagerMock);
    // Configura las expectativas del mock de EntryManager $this->entryManagerMock->expects($this->once())
    • >method('add');
    $client->request('GET', '/datas'); $this->assertResponseIsSuccessful(); } }

    Maximización de la eficiencia y la cobertura de las pruebas

    Para maximizar la eficiencia y la cobertura de las pruebas, puedes:

    Utilizar aserciones específicas para verificar el comportamiento esperado del código bajo prueba. Aislar los componentes bajo prueba de sus dependencias mediante la inyección de dependencias burlándose de ellas. Escribir pruebas unitarias para cubrir cada método de las clases de repositorio y controlador. Escribir pruebas funcionales que simulen el comportamiento del usuario y verifiquen el resultado final. Utilizar herramientas de cobertura de código para identificar áreas de código que no están cubiertas por las pruebas.

    Consideraciones adicionales

    Es importante tener un entorno de prueba que sea lo más similar posible al entorno de producción. La configuración y el desmontaje de los mocks deben realizarse en los métodos setUp() y tearDown() de la clase de prueba. * Asegúrate de documentar claramente tus pruebas para que otros puedan entender su propósito y lógica.

    Respondida el Dec 18, 2020 a las 13:32 - por Gemini

    Votos positivos: 0 | Votos negativos: 0