Tengo una clase que debería registrar algunas cosas. El registrador se define así.
export class Logger { public static client = ClientStrategy.create(); public async logSth(msg: string) { params = {"testThing": msg}; await Logger.client.updateItem(params); } export class ClientStrategy { public static create() { return new DatabaseClient(); // not important here just a factory, with a method updateItem } }Estoy tratando de burlarme de esto en una prueba de broma. Estoy tratando de simular esta estrategia de cliente y un método de creación para esto. Pero no funciona como esperaba.
jest.mock("./ClientStrategy"); const mockClientStrategy = jest.mocked(ClientStrategy, false); describe("Logger", () => { beforeEach(() => { jest.spyOn(<any>mockDatabaseClientStrategy, "create").mockImplementation(() => { return { updateItem: () => { return {} } }; }); }); it("should log sth", async () => { const response = await Logger.logSth("testMsg"); expect(response).not.tobeUndefined(); }); });pero obtengo No se puede leer la propiedad "logSth" de indefinido. ¿Puedes ayudarme qué estoy haciendo mal aquí? Creo que mi simulacro debería funcionar bien, pero desafortunadamente no tengo definición para esto.
Tanto jest.mock() como jest.spyOn() funcionarán. Pero no hay necesidad de usarlos juntos para su caso. Así que usemos jest.spyOn() para resolver tu problema.
Dado que ClientStrategy.create se ejecutará cuando importe la clase Logger , debe agregar un espía en ClientStrategy.create antes de importar la clase Logger .
Además, el método logSth es un método de instancia, NO un método de clase.
P.ej
Logger.ts :
import { ClientStrategy } from './ClientStrategy'; console.log('ClientStrategy.create: ', ClientStrategy.create); export class Logger { public static client = ClientStrategy.create(); public async logSth(msg: string) { const params = { testThing: msg }; return Logger.client.updateItem(params); } } Logger.test.ts :
import { ClientStrategy } from './ClientStrategy'; // import { Logger } from './Logger'; describe('Logger', () => { let mockClient; let Logger: typeof import('./Logger').Logger; beforeEach(async () => { mockClient = { updateItem: jest.fn(), }; jest.spyOn(ClientStrategy, 'create').mockReturnValue(mockClient); Logger = await import('./Logger').then((m) => m.Logger); }); afterEach(() => { jest.restoreAllMocks(); }); it('should log sth', async () => { mockClient.updateItem.mockResolvedValueOnce('fake value'); const logger = new Logger(); const response = await logger.logSth('testMsg'); expect(response).toEqual('fake value'); }); }); ClientStrategy.ts :
export class ClientStrategy { public static create() { return { updateItem: async (params) => 'real value' }; } }Resultado de la prueba:
PASS stackoverflow/71938329/Logger.test.ts Logger ✓ should log sth (22 ms) console.log ClientStrategy.create: [Function: mockConstructor] { _isMockFunction: true, getMockImplementation: [Function (anonymous)], mock: [Getter/Setter], mockClear: [Function (anonymous)], mockReset: [Function (anonymous)], mockRestore: [Function (anonymous)], mockReturnValueOnce: [Function (anonymous)], mockResolvedValueOnce: [Function (anonymous)], mockRejectedValueOnce: [Function (anonymous)], mockReturnValue: [Function (anonymous)], mockResolvedValue: [Function (anonymous)], mockRejectedValue: [Function (anonymous)], mockImplementationOnce: [Function (anonymous)], mockImplementation: [Function (anonymous)], mockReturnThis: [Function (anonymous)], mockName: [Function (anonymous)], getMockName: [Function (anonymous)] } at Object.<anonymous> (stackoverflow/71938329/Logger.ts:3:9) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 2.57 s, estimated 11 s Puede descomentar la import { Logger } from './Logger'; declaración y comente la import() para verificar el registro. Verá el método ClientStrategy.create sin burlar:
console.log ClientStrategy.create: [Function: create]