Descreva o erro
se eu sinon.createStubInstance(X)
onde X é uma classe com pelo menos um membro privado, recebo erros como:
Argumento do tipo 'SinonStubbedInstance
' não é atribuível ao parâmetro do tipo 'Foo'.
A propriedade '_private' está ausente no tipo 'SinonStubbedInstance' mas necessário no tipo '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);
});
});
Reproduzir
Etapas para reproduzir o comportamento:
printSpeech(mockFoo)
Comportamento esperado
Eu esperaria que isso funcionasse sem erros. Não me importo com _private(), nem pretendo testar diretamente seu comportamento, mas isso não deve resultar em um erro de tempo de compilação. Jasmine suporta este caso com jasmine.createSpyObj
, embora a implementação de jasmine tenha outras falhas.
Contexto (por favor, preencha as seguintes informações):
Ambiente: WSL Ubuntu 16.04, Nó 10
Outras bibliotecas que você está usando: Mocha 5.2.0
edit: aqui está um stackblitz https://stackblitz.com/edit/typescript-nfbgno?file=index.ts
Ele reclama do process.stdout porque está sendo executado no navegador, mas isso não é importante, pois o problema real é o tempo de compilação
Este é um problema datilografado. Não vamos gastar tempo analisando isso, pois não suportamos o Typescript explicitamente. Que o Typescript de alguma forma tenha suporte para membros privados é uma propriedade de seu sistema de tipos e pode ser implementado de várias maneiras. Quando usei o Typescript, muitas vezes resolvi esses problemas indo ao playground do Typescript e inspecionando a saída para entender o que ela fazia. Isso é o que você precisa fazer também.
Esta não é uma solução definitiva, mas consegui corrigir esse problema com a seguinte função:
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>;
}
Obviamente, isso não implementa nenhum método privado e, como tal, você não pode (e não deve por design) chamá-los. Ao usar esta função wrapper, você obtém a conclusão de código para todas as funções/membros públicos em sua classe, bem como as funções auxiliares de stub do sinon e StubbedClass
A resposta @pauloavelar ainda é a solução recomendada?
Comentários muito úteis
Esta não é uma solução definitiva, mas consegui corrigir esse problema com a seguinte função:
Obviamente, isso não implementa nenhum método privado e, como tal, você não pode (e não deve por design) chamá-los. Ao usar esta função wrapper, você obtém a conclusão de código para todas as funções/membros públicos em sua classe, bem como as funções auxiliares de stub do sinon e StubbedClassé um tipo válido para ser usado como T em seus testes.