clemens
Tengo problemas para simular un método estático en broma. Imagina que tienes una clase A con un método estático:
export default class A {
f() {
return 'a.f()'
}
static staticF () {
return 'A.staticF()'
}
}
Y una clase B que importa A
import A from './a'
export default class B {
g() {
const a = new A()
return a.f()
}
gCallsStaticF() {
return A.staticF()
}
}
Ahora quiere simular A. Es fácil simular f():
import A from '../src/a'
import B from '../src/b'
jest.mock('../src/a', () => {
return jest.fn().mockImplementation(() => {
return { f: () => { return 'mockedA.f()'} }
})
})
describe('Wallet', () => {
it('should work', () => {
const b = new B()
const result = b.g()
console.log(result) // prints 'mockedA.f()'
})
})
Sin embargo, no pude encontrar ninguna documentación sobre cómo simular A.staticF. es posible?
pedro stonham
Simplemente puede asignar el simulacro al método estático
import A from '../src/a'
import B from '../src/b'
jest.mock('../src/a')
describe('Wallet', () => {
it('should work', () => {
const mockStaticF = jest.fn().mockReturnValue('worked')
A.staticF = mockStaticF
const b = new B()
const result = b.gCallsStaticF()
expect(result).toEqual('worked')
})
})
-
Y luego también puedes hacer
expect(mockStaticF).toBeCalled()
aserciones de tipo, aunque la versión enlazada no funcionará (p. ej.expect(A.staticF).toBeCalled()
tiraría)– David A.
2 de diciembre de 2019 a las 11:04
-
Buena solución @Peter Realmente me salvaste el día en 2020. Muchas gracias.
– Mohit
19 de enero de 2020 a las 18:08
-
¿Por qué usar bind en este caso? ¿No podría ser más sencillo simplemente asignar
mockStaticF
aA.staticF
? p.ejA.staticF = mockStaticF
– Todd Bebe agua
3 de febrero de 2020 a las 7:28
-
también puede burlarse de ‘staticF’ fuera de ‘describe’, por ejemplo
jest.mock('../src/a', () => { const A = jest.fn().mockImplementation(() => { f: () => { return 'mockedA.f()'} } }); A.staticF = jest.fn(); return A; })
– franco
30 de abril de 2020 a las 22:08
-
Aquí hay dos problemas que no tienen en cuenta cómo funciona Jest. Nunca te burles de los métodos con asignaciones como
A.staticF = mockStaticF
si no puede evitar esto, esto evita que Jest restaure los métodos donde sea necesario y potencialmente da como resultado la contaminación cruzada de la prueba, para eso es jest.spyOn.jest.mock('../src/a')
hace un simulacro automático, ya hace que el método estático sea un código auxiliar que permiteA.staticF.mockReturnValue('worked')
.– Frasco de estus
8 de febrero de 2021 a las 12:29
Alex Minokis
Espero que esto te ayudará
// code to mock
export class AnalyticsUtil {
static trackEvent(name) {
console.log(name)
}
}
// mock
jest.mock('../src/AnalyticsUtil', () => ({
AnalyticsUtil: {
trackEvent: jest.fn()
}
}))
// code to mock
export default class Manager {
private static obj: Manager
static shared() {
if (Manager.obj == null) {
Manager.obj = new Manager()
}
return Manager.obj
}
nonStaticFunc() {
}
}
// mock
jest.mock('../src/Manager', () => ({
shared: jest.fn().mockReturnValue({
nonStaticFunc: jest.fn()
})
}))
// usage in code
someFunc() {
RNDefaultPreference.set('key', 'value')
}
// mock RNDefaultPreference
jest.mock('react-native-default-preference', () => ({
set: jest.fn()
}))
// code to mock
export namespace NavigationActions {
export function navigate(
options: NavigationNavigateActionPayload
): NavigationNavigateAction;
}
// mock
jest.mock('react-navigation', () => ({
NavigationActions: {
navigate: jest.fn()
}
}))
-
Fragmentos muy útiles! ¡Gracias!
– Frieder Bluemle
8 de enero de 2021 a las 2:27
Me las arreglé para burlarme de él en un archivo separado en el __mocks__
carpeta utilizando prototipos. Así que harías:
function A() {}
A.prototype.f = function() {
return 'a.f()';
};
A.staticF = function() {
return 'A.staticF()';
};
export default A;
Usando Object.assign
en el constructor simulado permite la simulación simultánea de la clase y sus métodos estáticos. Hacer esto le permite lograr la misma estructura que obtiene al crear una clase con miembros estáticos.
import A from '../src/a'
import B from '../src/b'
jest.mock('../src/a', () =>
Object.assign(
jest.fn(
// constructor
() => ({
// mock instance here
f: jest.fn()
})),
{
// mock static here
staticF: jest.fn(),
}
)
)
Necesitamos crear un simulacro y dar visibilidad al método simulado en el conjunto de pruebas. Debajo de la solución completa con comentarios.
let mockF; // here we make variable in the scope we have tests
jest.mock('path/to/StaticClass', () => {
mockF = jest.fn(() => Promise.resolve()); // here we assign it
return {staticMethodWeWantToMock: mockF}; // here we use it in our mocked class
});
// test
describe('Test description', () => {
it('here our class will work', () => {
ourTestedFunctionWhichUsesThisMethod();
expect(mockF).toHaveBeenCalled(); // here we should be ok
})
})
CTS_AE
Espías de broma
Fui con la ruta de usar jest.spyOn
.
Ejemplo
encryption.ts
export class Encryption {
static encrypt(str: string): string {
// ...
}
static decrypt(str: string): string {
// ...
}
}
property-encryption.spec.ts
import { Encryption } from './encryption'
import { PropertyEncryption } from './property-encryption'
describe('PropertyEncryption', () => {
beforeAll(() => {
jest
.spyOn(Encryption, 'encrypt')
.mockImplementation(() => 'SECRET')
jest
.spyOn(Encryption, 'decrypt')
.mockImplementation(() => 'No longer a secret')
})
it("encrypts object values and retains the keys", () => {
const encrypted = PropertyEncryption.encrypt({ hello: 'world' });
expect(encrypted).toEqual({ hello: 'SECRET' });
});
it("decrypts object values", () => {
const decrypted = PropertyEncryption.decrypt({ hello: "SECRET" });
expect(decrypted).toEqual({ hello: 'No longer a secret' });
});
})
guzmanoj
Aquí hay un ejemplo con una importación ES6.
import { MyClass } from '../utils/my-class';
const myMethodSpy = jest.spyOn(MyClass, 'foo');
describe('Example', () => {
it('should work', () => {
MyClass.foo();
expect(myMethodSpy).toHaveBeenCalled();
});
});