Muitos módulos de nó exportam uma única função (não uma função de construtor, mas uma função "utilitária" de propósito geral) como seu "módulo.exporta". É possível usar o Sinon.js para fazer o stub dessa função autônoma?
// some module, "sum.js" that's "required" throughout the application
module.exports = function(a, b) {
return a + b;
};
// test.js
var sum = require('sum');
...
beforeEach(function() {
sumStub = sinon.stub(sum);
// throws: TypeError: Attempted to wrap undefined property undefined as function
});
afterEach(function() {
sumStub.restore();
});
...
Existe alguma maneira de conseguir isso?
Infelizmente não.
Para npm, você pode usar https://github.com/thlorenz/proxyquire ou semelhante. Michael Feathers chamaria isso de costura de ligação .
Não é elegante, mas factível.
Depois de fazer isso, você pode usar o Sinon normalmente.
No longo prazo, você pode querer mover sua arquitetura em direção a _object costuras_, mas é uma solução que funciona hoje. Existem projetos semelhantes para RequireJS.
function MyFunction(){}
module.exports = function(){ return module.exports.MyFunction.apply(this, arguments) }
module.exports.MyFunction = MyFunction
Em seguida, você pode criar um stub para require ('./ MyFunction'). MyFunction e o resto do seu código sem alteração verá a edição em stub.
: tonto:: tonto_face:: tonto:
Encontrei a mesma coisa outro dia, eis o que fiz:
const proxyquire = require('proxyquire')
const sinon = require('sinon')
const sum = sinon.stub()
const ModuleWithDependency = proxyquire('module', {
'sum': sum
})
funciona muito bem para o nosso caso.
Se estiver usando CommonJS:
const myStubbedModule = function( absoluteModulePath ) {
const stub = sinon.stub();
require.cache[ require.resolve( absoluteModulePath ) ] = stub;
return stub;
}
_Nota_: Dependendo se você está transpilando, você pode precisar fazer:
require.cache[ require.resolve( absoluteModulePath ) ] = {
default: stub,
exports: stub
}
Freqüentemente, durante os testes, preciso inserir um esboço para um teste específico. A abordagem de função de invólucro que usei me permite modificar a base de código e inserir meus stubs sempre que eu quiser, sem ter que adotar uma abordagem stub-first ou jogar whack-a-mole com módulos tendo referências a outros módulos que estou tentando stub e substituir no local.
Eu tive uma série de revisões de código em que as pessoas me incentivaram a hackear a camada do módulo Node, via proxyquire, mock-require etc. necessário no local durante a configuração do teste. Com proxyquire, pelo menos um pode proxyquire () uma versão do tamanho de um micro / dispositivo elétrico do aplicativo, algo de nível superior, e todos os stubs serão trazidos durante o carregamento, mas lidar com isso em um nível de linguagem JS em vez de nível de módulo Node continua para me parecer significativamente mais simples e fácil de gerenciar de forma consistente e sem perigo (advertência: desde que se lembre de restaurar).
Fiz este módulo para módulos stub mais facilmente https://github.com/caiogondim/stubbable-decorator.js
Eu estava apenas brincando com o Sinon e encontrei uma solução simples que parece estar funcionando - basta adicionar 'argumentos' como um segundo argumento
const sumStub = sinon.stub(sum, 'arguments');
sumStub.withArgs(2, 2).returns(4);
sumStub.withArgs(3, 3).returns(6);
Tente isto
import * as sum from './sum'
sinon.stub(sum, 'default', () => {
// stubbed function
});
@ harryi3t - obrigado, funcionou para mim.
@ harryi3t Isso não funcionou para mim, usando os Módulos ES.
Erro: can't redefine non-configurable property "default"
Módulos @elliottregan ES não são stubbable de acordo com o PADRÃO. Temos até testes que cobrem esse comportamento. Você ainda pode fazer isso, como discuto aqui .
Muitas pessoas não estão realmente testando os Módulos ES, mas sim os Módulos ES transpilados (usando Webpack / Babel, etc). O ES5 resultante usa getters para emular como os Módulos ES funcionam. Você pode estar fazendo isso, mas tente o caminho simples que sugiro no tópico vinculado. mocha --register ...
leva você longe.
Possível solução
(function (defineProperty) {
Object.defineProperty = (obj, prop, desc) => {
desc.configurable = true;
return defineProperty(obj, prop, desc);
};
})(Object.defineProperty);
@Sujimoshi Solução alternativa para o quê exatamente? Qual é o contexto para sua correção? Além disso, onde as pessoas colocariam a correção? Em sua encarnação atual, está faltando um pouco de informação demais para ser útil. Isso não ajudaria na pergunta original e não funcionaria para os Módulos ES . Eu estou supondo que se refere ao código que foi processado pelo Webpack 4, pois pode se aplicar (dependendo de sua cadeia de ferramentas) ao código escrito usando a sintaxe ES2015 + que foi _transpilada_ no ES5, _emulando_ a imutabilidade dos Módulos ES por meio de descritores de objeto não configuráveis .
Tente isto
import * as sum from './sum' sinon.stub(sum, 'default', () => { // stubbed function });
obsoleto agora.
Acabei de reescrever meu módulo ES6 a partir deste:
export default const doCoolStuff = () => {
// do the cool stuff...
}
para isso:
export default {
doCoolStuff: () => {
// do the cool stuff...
}
}
É um pouco desajeitado, mas me permitiu envolver a função em um esboço.
agora é quase 2021, é possível?
agora é quase 2021, é possível?
Não é muito diferente de 2019.
Módulos ES não mudaram, CommonJS não mudou, JavaScript não mudou.
Comentários muito úteis
Tente isto