es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Prueba de unidad con monkey patch en Angular (No se pueden leer las propiedades de undefined (leyendo ‘checkABC’))

Estoy intentando probar unitariamente mi método setStep() en angular usando Jasmine, pero sigo obteniendo “Cannot read properties of undefined (reading ‘checkBusiness’)” lo cual me impide continuar con la prueba.

Esta es la función en el archivo component.ts:

get userBusiness(): string { return this.auth && this.auth.user && this.auth.user.Source; }

setSteps() {
    if (this.userBusiness.checkBusiness('ABC')) {
      this.items = steps['ABC'];
      if (this.application.process.onboarding.status !== 'complete') { this.show = true; }
    } else {
      this.items = steps['DEF'];
    }
}

El método “checkBusiness()” está definido como un monkey patch para la clase prototype de String:

Interface String {
  checkBusiness(...args: string[]): boolean;
}

String.prototype.checkBusiness = function(...args: string[]): boolean {
  let result = false;
  for (let arg of args) {
    const currentBusinessArray = business[this];
    if (!currentBusinessArray) {
      result = false;
      continue;
    }

    if (currentBusinessArray.includes(arg)) {
      result = true;
    }
  }
  return result;
};

“Business” es un array definido de la siguiente manera:

const lob = Object.freeze( {
ABC: [‘ABC’, ‘ABC1’, ‘ABC2’, ‘ABC3’],
DEF: [‘DEF’, ‘DEF1’, ‘DEF2’, ‘DEF3’]
});

Archivo de prueba (spec):

it('should confirm that "show" is set to true in setSteps()', () => {
  const testUserBusiness = {...testDataSvc.userABC}
  const userBusinessSpy = spyOnProperty(component, 'userBusiness').and.returnValue(testUserBusiness);
  console.log(component['userBusiness']);
  component.setSteps();
})

Problema:
Sigo obteniendo “Cannot read properties of undefined (reading ‘checkBusiness’)”.

¿Alguna idea de cómo superar esto? He intentado buscar en todas partes pero no hay un escenario similar que pueda seguir.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Parece que el error se debe al hecho de que el método checkBusiness() no está definido en el prototipo de String dentro del entorno de prueba unitaria. Tiene sentido, ya que parchear los prototipos integrados generalmente se considera una mala práctica.

    Un par de opciones para solucionar este problema:

    1. Refactorizar el método checkBusiness() en una función de utilidad separada que se pueda importar fácilmente tanto en el archivo del componente como en el archivo de prueba unitaria.

    Por ejemplo:

    export function checkBusiness(source: string, ...args: string[]): boolean {
      let result = false;
      for (let arg of args) {
        const currentBusinessArray = business[source];
        if (!currentBusinessArray) {
          result = false;
          continue;
        }
    
        if (currentBusinessArray.includes(arg)) {
          result = true;
        }
      }
      return result;
    };
    

    Luego puedes importar esta función en el archivo del componente y usarla de la siguiente manera:

    import { checkBusiness } from 'ruta/al/archivo/de/utilidad';
    
    setSteps() {
        if (checkBusiness(this.userBusiness, 'ABC')) {
          this.items = steps['ABC'];
          if (this.application.process.onboarding.status !== 'complete') { this.show = true; }
        } else {
          this.items = steps['DEF'];
        }
      }
    

    Y en el archivo de prueba unitaria:

    import { checkBusiness } from 'ruta/al/archivo/de/utilidad';
    
    it('should confirm that "show" is set to true in setSteps()', () => {
        const testUserBusiness = {...testDataSvc.userABC}
        spyOnProperty(component, 'userBusiness').and.returnValue(testUserBusiness);
        spyOn(window, 'checkBusiness').and.returnValue(true);
        component.setSteps();
        expect(component.show).toBe(true);
      })
    

    Ten en cuenta que en el archivo de prueba estamos usando el método spyOn() para simular la función checkBusiness() y devolver un valor de true con fines de prueba.

    1. Otra opción sería simular el método checkBusiness() directamente en el prototipo de String dentro del archivo de prueba unitaria, agregando el siguiente código:
    // Simular el método checkBusiness en el prototipo String
    String.prototype.checkBusiness = function(...args: string[]): boolean {
      return true;
    };
    

    Esto debería solucionar el problema con la prueba unitaria actual, pero como se mencionó anteriormente, no es una buena práctica modificar los prototipos integrados de esta manera.

    Se recomienda utilizar la primera opción y refactorizar el método checkBusiness() en una función de utilidad separada.

Comments are closed.