Este é um exemplo trivial que ilustra o cerne do meu problema:
var innerLib = require('./path/to/innerLib');
function underTest() {
return innerLib.doComplexStuff();
}
module.exports = underTest;
Estou tentando escrever um teste de unidade para este código. Como posso zombar do requisito do innerLib
sem zombar require
totalmente da função?
Então, sou eu que estou tentando zombar do global require
e descobrindo que ele não funcionará nem para fazer isso:
var path = require('path'),
vm = require('vm'),
fs = require('fs'),
indexPath = path.join(__dirname, './underTest');
var globalRequire = require;
require = function(name) {
console.log('require: ' + name);
switch(name) {
case 'connect':
case indexPath:
return globalRequire(name);
break;
}
};
O problema é que a require
função dentro do underTest.js
arquivo não foi realmente zombada. Ainda aponta para a require
função global . Parece que só posso zombar da require
função no mesmo arquivo em que estou zombando. Se eu usar o global require
para incluir qualquer coisa, mesmo depois de substituir a cópia local, os arquivos solicitados ainda terão o require
referência global .
javascript
node.js
mocking
Matthew Taylor
fonte
fonte
global.require
. As variáveis gravammodule
por padrão, pois os módulos têm escopo definido no módulo.Respostas:
Agora você pode!
I publicado proxyquire que vai cuidar de substituir exigem o mundial dentro do seu módulo enquanto estiver testando ele.
Isso significa que você não precisa de alterações no seu código para injetar zombarias nos módulos necessários.
O Proxyquire possui uma API muito simples, que permite resolver o módulo que você está tentando testar e repassar zombarias / stubs para os módulos necessários em uma única etapa.
A @Raynos está certa de que, tradicionalmente, você tinha que recorrer a soluções não muito ideais para conseguir isso ou fazer um desenvolvimento de baixo para cima
Qual é a principal razão pela qual eu criei o proxyquire - para permitir o desenvolvimento orientado a testes de cima para baixo sem qualquer aborrecimento.
Dê uma olhada na documentação e nos exemplos para avaliar se ela atenderá às suas necessidades.
fonte
proxyquire
!Uma opção melhor nesse caso é zombar dos métodos do módulo retornado.
Para melhor ou pior, a maioria dos módulos node.js. são singletons; dois pedaços de código que requerem () o mesmo módulo obtêm a mesma referência a esse módulo.
Você pode aproveitar isso e usar algo como sinon para zombar dos itens necessários. teste mocha a seguir:
O Sinon tem uma boa integração com o chai para fazer afirmações, e eu escrevi um módulo para integrar o sinon ao mocha para facilitar a limpeza de espiões / stub (para evitar a poluição nos testes).
Observe que underTest não pode ser ridicularizado da mesma maneira, pois underTest retorna apenas uma função.
Outra opção é usar zombarias Jest. Acompanhamento na página deles
fonte
require('some_module')
, porque todo o seu código compartilha o mesmo diretório node_modules. Segundo, o artigo está confundindo o espaço de nome com os singletons, o que é uma espécie de ortogonal. Terceiro, esse artigo é muito antigo (no que diz respeito ao node.js), então o que poderia ter sido válido naquele dia talvez não seja válido agora.innerLib.toCrazyCrap.restore()
e restub, ou ligue sinon viasinon.stub(innerLib, 'toCrazyCrap')
que lhe permite mudar a forma como se comporta stub:innerLib.toCrazyCrap.returns(false)
. Além disso, a religação parece ser muito parecida com aproxyquire
extensão acima.Eu uso mock-exigem . Certifique-se de definir suas zombarias antes
require
de testar o módulo.fonte
Zombar
require
parece um truque desagradável para mim. Eu pessoalmente tentaria evitá-lo e refatorar o código para torná-lo mais testável. Existem várias abordagens para lidar com dependências.1) passar dependências como argumentos
Isso tornará o código universalmente testável. A desvantagem é que você precisa repassar dependências, o que pode tornar o código mais complicado.
2) implemente o módulo como uma classe e use métodos / propriedades de classe para obter dependências
(Este é um exemplo artificial, em que o uso da classe não é razoável, mas transmite a ideia) (exemplo ES6)
Agora você pode facilmente stub
getInnerLib
método para testar seu código. O código se torna mais detalhado, mas também mais fácil de testar.fonte
colors
módulo que messes comString.prototype
)Se você já usou o gracejo, provavelmente conhece o recurso simulado do gracejo.
Usando "jest.mock (...)", você pode simplesmente especificar a string que ocorreria em uma instrução de requisição em seu código em algum lugar e sempre que um módulo for necessário usando essa string, um objeto simulado será retornado.
Por exemplo
substituiria completamente todas as importações / exigências de "firebase-admin" pelo objeto que você retornou dessa função "factory".
Bem, você pode fazer isso ao usar o gracejo, porque o gracejo cria um tempo de execução em torno de cada módulo executado e injeta uma versão "viciada" do requisito no módulo, mas você não seria capaz de fazer isso sem o gracejo.
Eu tentei conseguir isso com mock-require, mas para mim não funcionou para níveis aninhados na minha fonte. Dê uma olhada no seguinte problema no github: mock-require nem sempre chamado com Mocha .
Para resolver isso, criei dois módulos npm que você pode usar para alcançar o que deseja.
Você precisa de um plug-in babel e de um mocker de módulo.
No seu .babelrc, use o plug-in babel-plugin-mock-require com as seguintes opções:
e no seu arquivo de teste, use o módulo jestlike-mock da seguinte maneira:
O
jestlike-mock
módulo ainda é muito rudimentar e não possui muita documentação, mas também não há muito código. Aprecio todos os PRs para um conjunto de recursos mais completo. O objetivo seria recriar todo o recurso "jest.mock".Para ver como o jest implementa, é possível procurar o código no pacote "jest-runtime". Veja https://github.com/facebook/jest/blob/master/packages/jest-runtime/src/index.js#L734, por exemplo, aqui eles geram um "automock" de um módulo.
Espero que ajude ;)
fonte
Você não pode. Você precisa construir seu conjunto de testes unitários para que os módulos mais baixos sejam testados primeiro e que os módulos de nível superior que requerem módulos sejam testados posteriormente.
Você também deve assumir que qualquer código de terceiros e o próprio node.js sejam bem testados.
Presumo que você verá estruturas de simulação chegando em um futuro próximo que sobrescrevem
global.require
Se você realmente precisa injetar uma simulação, pode alterar seu código para expor o escopo modular.
Esteja ciente de que isso se expõe
.__module
à sua API e qualquer código pode acessar o escopo modular por seu próprio perigo.fonte
Você pode usar a biblioteca de zombaria :
fonte
Código simples para simular módulos para os curiosos
Observe as partes em que você manipula o método
require.cache
e observerequire.resolve
, pois esse é o molho secreto.Use como :
MAS ... proxyquire é bastante impressionante e você deve usá-lo. Ele mantém as substituições necessárias localizadas apenas nos testes e eu recomendo.
fonte