Lors du test d'un module qui a une dépendance dans un fichier différent. Lorsque vous attribuez à ce module un script typographique, jest.Mock
une erreur mockReturnThisOnce
indique que la méthode (ou toute autre méthode jest.Mock) n'existe pas sur la dépendance, c'est parce qu'elle est précédemment tapée. Quelle est la bonne façon d'obtenir du typecript pour hériter des types de jest.Mock?
Voici un exemple rapide.
Dépendance
const myDep = (name: string) => name;
export default myDep;
test.ts
import * as dep from '../depenendency';
jest.mock('../dependency');
it('should do what I need', () => {
//this throws ts error
// Property mockReturnValueOnce does not exist on type (name: string)....
dep.default.mockReturnValueOnce('return')
}
J'ai l'impression que c'est un cas d'utilisation très courant et je ne sais pas comment le saisir correctement. Toute aide serait très appréciée!
javascript
unit-testing
typescript
jestjs
Philippe Chmalts
la source
la source
import
sont évalués en premier, peu importe si vous mettez du code avant l'importation. Donc ça ne marchera pas.mock...
Réponses:
Vous pouvez utiliser la diffusion de type et votre
test.ts
devrait ressembler à ceci:import * as dep from '../dependency'; jest.mock('../dependency'); const mockedDependency = <jest.Mock<typeof dep.default>>dep.default; it('should do what I need', () => { //this throws ts error // Property mockReturnValueOnce does not exist on type (name: string).... mockedDependency.mockReturnValueOnce('return'); });
TS transpiler n'est pas conscient du fait que les
jest.mock('../dependency');
changements de typedep
doivent être utilisés. Comme importédep
n'est pas une définition de type, vous devez obtenir son type avectypeof dep.default
.Voici quelques autres modèles utiles que j'ai trouvés lors de mon travail avec Jest et TS
Lorsque l'élément importé est une classe, vous n'avez pas besoin d'utiliser typeof par exemple:
import { SomeClass } from './SomeClass'; jest.mock('./SomeClass'); const mockedClass = <jest.Mock<SomeClass>>SomeClass;
Cette solution est également utile lorsque vous devez vous moquer de certains modules natifs de nœuds:
import { existsSync } from 'fs'; jest.mock('fs'); const mockedExistsSync = <jest.Mock<typeof existsSync>>existsSync;
Au cas où vous ne voudriez pas utiliser la simulation automatique de plaisanterie et préférez en créer une manuelle
import TestedClass from './TestedClass'; import TestedClassDependency from './TestedClassDependency'; const testedClassDependencyMock = jest.fn<TestedClassDependency>(() => ({ // implementation })); it('Should throw an error when calling playSomethingCool', () => { const testedClass = new TestedClass(testedClassDependencyMock()); });
testedClassDependencyMock()
crée une instance d'objet simuléTestedClassDependency
peut être une classe, un type ou une interfacela source
jest.fn(() =>...
place dejest.fn<TestedClassDependency>(() =>...
(je viens de supprimer le type de casting après jest.fn) car IntelliJ se plaint. Sinon cette réponse m'a aidé merci! En utilisant ceci dans mon package.json: "@ types / jest": "^ 24.0.3"jest.mock('./SomeClass');
code ci-dessus?<jest.Mock<SomeClass>>SomeClass
expression produit une erreur TS pour moi:Conversion of type 'typeof SomeClass' to type 'Mock<SomeClass, any>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Type 'typeof SomeClass' is missing the following properties from type 'Mock<SomeClass, any>': getMockName, mock, mockClear, mockReset, and 11 more.ts(2352)
Utilisez l'
mocked
aide dets-jest
comme expliqué ici// foo.spec.ts import { mocked } from 'ts-jest/utils' import { foo } from './foo' jest.mock('./foo') // here the whole foo var is mocked deeply const mockedFoo = mocked(foo, true) test('deep', () => { // there will be no TS error here, and you'll have completion in modern IDEs mockedFoo.a.b.c.hello('me') // same here expect(mockedFoo.a.b.c.hello.mock.calls).toHaveLength(1) }) test('direct', () => { foo.name() // here only foo.name is mocked (or its methods if it's an object) expect(mocked(foo.name).mock.calls).toHaveLength(1) })
et si
tslint
ts-jest
est dans vos dépendances de développement,ajoutez cette règle à votre
tslint.json
:"no-implicit-dependencies": [true, "dev"]
la source
ts-jest
et de classes: github.com/tbinna/ts-jest-mock-examples et cet article: stackoverflow.com/questions/58639737/…J'utilise le modèle de @ types / jest / index.d.ts juste au-dessus du type def pour Mocked (ligne 515):
import { Api } from "../api"; jest.mock("../api"); const myApi: jest.Mocked<Api> = new Api() as any; myApi.myApiMethod.mockImplementation(() => "test");
la source
const myApi = new Api() as jest.Mocked<Api>;
jest.Mock<Api>
. Vous devrez y allerconst myApi = new Api() as any as jest.Mock<Api>
et je dirais que celle ci-dessus est un peu meilleure que la double affirmation."strict": true
dans tsconfig.json. Cela couvre des choses commenoImplicitAny
,strictNullChecks
etc., vous n'avez donc pas à le définir individuellement pour eux.myApi
-à- dire ? Il ne stub de manière générique toutes les autres instances initiées par la classeApi
dans le module testé, non?Il existe deux solutions, les deux sont la fonction souhaitée
1) Utilisez jest.MockedFunction
import * as dep from './dependency'; jest.mock('./dependency'); const mockMyFunction = dep.myFunction as jest.MockedFunction<typeof dep.myFunction>;
2) Utilisez jest.Mock
import * as dep from './dependency'; jest.mock('./dependency'); const mockMyFunction = dep.default as jest.Mock;
Il n'y a aucune différence entre ces deux solutions. Le second est plus court et je suggère donc de l'utiliser.
Les deux solutions de casting permettent d'appeler n'importe quelle fonction de simulation de plaisanterie sur
mockMyFunction
likemockReturnValue
oumockResolvedValue
https://jestjs.io/docs/en/mock-function-api.htmlmockMyFunction.mockReturnValue('value');
mockMyFunction
peut être utilisé normalement pour attendreexpect(mockMyFunction).toHaveBeenCalledTimes(1);
la source
Jeter
as jest.Mock
Le simple fait de lancer la fonction en
jest.Mock
devrait faire l'affaire:(dep.default as jest.Mock).mockReturnValueOnce('return')
la source
Voici ce que j'ai fait avec [email protected] et [email protected] :
la source:
class OAuth { static isLogIn() { // return true/false; } static getOAuthService() { // ... } }
tester:
import { OAuth } from '../src/to/the/OAuth' jest.mock('../src/utils/OAuth', () => ({ OAuth: class { public static getOAuthService() { return { getAuthorizationUrl() { return ''; } }; } } })); describe('createMeeting', () => { test('should call conferenceLoginBuild when not login', () => { OAuth.isLogIn = jest.fn().mockImplementationOnce(() => { return false; }); // Other tests }); });
Voici comment se moquer d'une classe non par défaut et de ses méthodes statiques:
jest.mock('../src/to/the/OAuth', () => ({ OAuth: class { public static getOAuthService() { return { getAuthorizationUrl() { return ''; } }; } } }));
Voici une conversion de type du type de votre classe vers
jest.MockedClass
ou quelque chose comme ça. Mais cela finit toujours par des erreurs. Je l'ai donc utilisé directement et cela a fonctionné.test('Some test', () => { OAuth.isLogIn = jest.fn().mockImplementationOnce(() => { return false; }); });
Mais, si c'est une fonction, vous pouvez vous en moquer et faire la conversation de type.
jest.mock('../src/to/the/Conference', () => ({ conferenceSuccessDataBuild: jest.fn(), conferenceLoginBuild: jest.fn() })); const mockedConferenceLoginBuild = conferenceLoginBuild as jest.MockedFunction< typeof conferenceLoginBuild >; const mockedConferenceSuccessDataBuild = conferenceSuccessDataBuild as jest.MockedFunction< typeof conferenceSuccessDataBuild >;
la source
J'ai trouvé ceci dans
@types/jest
:/** * Wrap a function with mock definitions * * @example * * import { myFunction } from "./library"; * jest.mock("./library"); * * const mockMyFunction = myFunction as jest.MockedFunction<typeof myFunction>; * expect(mockMyFunction.mock.calls[0][0]).toBe(42); */
Remarque: Lorsque vous faites
const mockMyFunction = myFunction
et puis quelque chose commemockFunction.mockReturnValue('foo')
, vous changezmyFunction
également.Source: https://github.com/DefinitelyTyped/DefinatelyTyped/blob/master/types/jest/index.d.ts#L1089
la source
Une bibliothèque récente résout ce problème avec un plugin babel: https://github.com/userlike/joke
Exemple:
import { mock, mockSome } from 'userlike/joke'; const dep = mock(import('./dependency')); // You can partially mock a module too, completely typesafe! // thisIsAMock has mock related methods // thisIsReal does not have mock related methods const { thisIsAMock, thisIsReal } = mockSome(import('./dependency2'), () => ({ thisIsAMock: jest.fn() })); it('should do what I need', () => { dep.mockReturnValueOnce('return'); }
Soyez conscient de cela
dep
etmockReturnValueOnce
sont entièrement sûrs. De plus, tsserver sait qu'il adepencency
été importé et auquel il a été assigné afindep
que toutes les refactorisations automatiques prises en charge par tsserver fonctionnent également.Remarque: je gère la bibliothèque.
la source