O módulo A
inclui import B
na parte superior. No entanto, sob condições de teste gostaria de zombar B
em A
(simulado A.B
) e completamente abster-se de importação B
.
De fato, B
não é instalado no ambiente de teste de propósito.
A
é a unidade em teste. Eu tenho que importar A
com todas as suas funcionalidades. B
é o módulo que eu preciso zombar. Mas como posso zombar por B
dentro A
e parar A
de importar o real B
, se a primeira coisa A
que importa é importar B
?
(A razão pela qual B não está instalado é que eu uso o pypy para testes rápidos e, infelizmente, B ainda não é compatível com o pypy.)
Como isso poderia ser feito?
fonte
Mock
não irá corrigir alguns atributos mágicos (__%s__
) como__name__
.sys.modules['B'] = None
mas não parece funcionar.mock
e ligarmock.Mock()
O builtin
__import__
pode ser ridicularizado com a biblioteca 'mock' para mais controle:Diga se
A
parece com:A.a()
retornosb_mock.func()
que também podem ser ridicularizados.Nota para Python 3: Conforme declarado no log de alterações do 3.0 ,
__builtin__
agora é nomeadobuiltins
:O código nesta resposta funcionará bem se você substituir
__builtin__
pelobuiltins
Python 3.fonte
import_mock
ser chamado para oimport A
, mas não para qualquer coisa que importa.ImportError: No module named '__builtin__'
__builtin__
__builtin__
porbuiltins
para python3 ( docs.python.org/3/whatsnew/3.0.html?highlight=__builtin__ )Fácil, basta zombar da biblioteca em sys.modules antes de ser importada:
e, desde
A
que não dependa de tipos específicos de dados retornados dos objetos de B:deve funcionar.
Você também pode zombar
import A.B
:Isso funciona mesmo se você tiver submódulos, mas você deseja zombar de cada módulo. Digamos que você tenha o seguinte:
Para zombar, basta fazer o seguinte antes que o módulo que contém os itens acima seja importado:
(Minha experiência: eu tinha uma dependência que funciona em uma plataforma, Windows, mas não funcionava no Linux, onde executamos nossos testes diários. Então, eu precisava zombar da dependência de nossos testes. Felizmente, era uma caixa preta, então Não precisei criar muita interação.)
Zombando de efeitos colaterais
Adendo: Na verdade, eu precisava simular um efeito colateral que levou algum tempo. Então, eu precisava do método de um objeto para dormir por um segundo. Isso funcionaria assim:
E então o código leva algum tempo para ser executado, assim como o método real.
fonte
Sei que estou um pouco atrasado para a festa aqui, mas aqui está uma maneira um tanto insana de automatizar isso com a
mock
biblioteca:(aqui está um exemplo de uso)
A razão pela qual isso é ridiculamente complicado é quando ocorre uma importação, o python basicamente faz isso (por exemplo
from herp.derp import foo
)sys.modules['herp']
? Caso contrário, importe-o. Se ainda nãoImportError
sys.modules['herp.derp']
? Caso contrário, importe-o. Se ainda nãoImportError
foo
desys.modules['herp.derp']
. OutroImportError
foo = sys.modules['herp.derp'].foo
Existem algumas desvantagens nessa solução hackeada: se algo mais depende de outras coisas no caminho do módulo, esse tipo de coisa é demais. Além disso, isso só funciona para coisas que estão sendo importadas em linha, como
ou
fonte
A resposta de Aaron Hall funciona para mim. Só quero mencionar uma coisa importante,
se
A.py
você fazfrom B.C.D import E
então
test.py
você deve zombar de todos os módulos ao longo do caminho, caso contrário, você obtémImportError
fonte
Encontrei uma boa maneira de zombar das importações em Python. É a solução Zaadi de Eric encontrada aqui, que eu apenas uso dentro do meu aplicativo Django .
Eu tenho classe
SeatInterface
que é interface paraSeat
classe de modelo. Então, dentro do meuseat_interface
módulo, eu tenho essa importação:Eu queria criar testes isolados para
SeatInterface
classe comSeat
classe zombada comoFakeSeat
. O problema era - como você executa os testes offline, onde o aplicativo Django está inoperante. Eu tive abaixo do erro:A solução foi:
E então teste magicamente executa OK :)
fonte
Se você faz um,
import ModuleB
está realmente chamando o método embutido__import__
como:Você pode sobrescrever esse método importando o
__builtin__
módulo e criando um invólucro em torno do__builtin__.__import__
método. Ou você pode jogar com oNullImporter
gancho doimp
módulo. Capturando a exceção e zombando de seu módulo / classe noexcept
blocoPonteiro para os documentos relevantes:
docs.python.org:
__import__
Acessando Internos de Importação com o Módulo imp
Eu espero que isso ajude. Seja ALTAMENTE avisado de que você adentra os perímetros mais misteriosos da programação em python e que a) é sólida a compreensão do que você realmente deseja alcançar eb) a compreensão profunda das implicações é importante.
fonte