Sinon: Impossible de créer StubInstance sur une classe avec des membres privés

Créé le 4 janv. 2019  ·  3Commentaires  ·  Source: sinonjs/sinon

Décrivez le bogue
si je sinon.createStubInstance(X) où X est une classe avec au moins un membre privé, je reçois des erreurs comme :

Argument de type 'SinonStubbedInstance' n'est pas assignable au paramètre de type 'Foo'.
La propriété '_private' est manquante dans le type 'SinonStubbedInstance' mais obligatoire dans le type 'Foo'.

describe('SinonTest', () => {
  class Foo {
    public talk() {
      return 'hi';
    }
    private _private() {
      return null;
    }
  }

  function printSpeech(foo: Foo) {
    console.log(foo.talk());
  }
  it('should allow you to pass a stub as a the original', () => {
    const mockFoo = sinon.createStubInstance(Foo);

    printSpeech(mockFoo);
  });
});

Reproduire
Étapes pour reproduire le comportement :

  1. Monter un projet avec moka et sinon.
  2. Créer un fichier de spécification de test unitaire
  3. Collez l'extrait de code ci-dessus et ajoutez les importations requises
  4. Voir erreur en ligne avec printSpeech(mockFoo)

Comportement attendu
Je m'attendrais à ce que cela fonctionne sans erreur. Je ne me soucie pas de _private(), et je n'ai pas non plus l'intention de tester directement son comportement, mais cela ne devrait pas entraîner d'erreur de construction. Jasmine prend en charge ce cas avec jasmine.createSpyObj , bien que l'implémentation de jasmine ait d'autres défauts.

Contexte (veuillez compléter les informations suivantes) :

  • Version de la bibliothèque : sinon : 7.2.2, @types/sinon : 7.0.3
  • Environnement : WSL Ubuntu 16.04, nœud 10

  • Autres bibliothèques que vous utilisez : Mocha 5.2.0

edit : voici un stackblitz https://stackblitz.com/edit/typescript-nfbgno?file=index.ts

Il se plaint de process.stdout car il s'exécute dans le navigateur, mais ce n'est pas important car le problème réel est au moment de la compilation

Commentaire le plus utile

Ce n'est pas une solution définitive, mais j'ai réussi à résoudre ce problème avec la fonction suivante :

import { createStubInstance, StubbableType, SinonStubbedInstance, SinonStubbedMember } from 'sinon';

export type StubbedClass<T> = SinonStubbedInstance<T> & T;

export function createSinonStubInstance<T>(
  constructor: StubbableType<T>,
  overrides?: { [K in keyof T]?: SinonStubbedMember<T[K]> },
): StubbedClass<T> {
  const stub = createStubInstance<T>(constructor, overrides);
  return stub as unknown as StubbedClass<T>;
}

Évidemment, cela n'implémente aucune méthode privée, et en tant que tel, vous ne pouvez pas (et ne devriez pas par conception) les appeler. En utilisant cette fonction wrapper, vous obtenez la complétion de code pour toutes les fonctions/membres publics de votre classe ainsi que les fonctions d'assistance de stub de sinon et StubbedClassest un type valide à utiliser comme T dans vos tests.

Tous les 3 commentaires

Il s'agit d'un problème de dactylographie. Nous n'allons pas perdre de temps à examiner cela, car nous ne prenons pas explicitement en charge Typescript. Que Typescript ait en quelque sorte un support pour les membres privés est une propriété de son système de type et pourrait être implémenté de plusieurs façons. Lorsque j'utilisais Typescript, je résolvais souvent ces problèmes en allant sur le terrain de jeu Typescript et en inspectant la sortie pour comprendre ce qu'elle faisait. C'est ce que vous devez faire aussi.

Ce n'est pas une solution définitive, mais j'ai réussi à résoudre ce problème avec la fonction suivante :

import { createStubInstance, StubbableType, SinonStubbedInstance, SinonStubbedMember } from 'sinon';

export type StubbedClass<T> = SinonStubbedInstance<T> & T;

export function createSinonStubInstance<T>(
  constructor: StubbableType<T>,
  overrides?: { [K in keyof T]?: SinonStubbedMember<T[K]> },
): StubbedClass<T> {
  const stub = createStubInstance<T>(constructor, overrides);
  return stub as unknown as StubbedClass<T>;
}

Évidemment, cela n'implémente aucune méthode privée, et en tant que tel, vous ne pouvez pas (et ne devriez pas par conception) les appeler. En utilisant cette fonction wrapper, vous obtenez la complétion de code pour toutes les fonctions/membres publics de votre classe ainsi que les fonctions d'assistance de stub de sinon et StubbedClassest un type valide à utiliser comme T dans vos tests.

La réponse @pauloavelar est-elle toujours la solution de contournement recommandée ?

Cette page vous a été utile?
0 / 5 - 0 notes