LINUX.ORG.RU

mock не mock'ает.

 , , ,


0

2

Использую mock в модульных (unit) тестах. Столкнулся с тем, что могу заменить вызов оригинальных функций mock'ами в сторонних библиотеках и функций из того же файла что и тестируемая функция, но не могу заменить функции из других файлов моей же программы. ЧЯДНТ? Кто-нибудь сталкивался с подобным?

★★★★★

Ответ на: комментарий от Novel

Пример.

#./ehlo/ehlo.py

def say_ehlo():
    print 'EHLO'
    return False

Определили функцию ehlo(), которая выводит в консоль 'EHLO'

#./hello/hello.py
from ehlo.ehlo import say_ehlo


def say_hello():
    print 'hello'
    return True


def say_hello_ehlo():
    say_hello()
    say_ehlo()
    return True
Обратите внимание на say_hello_ehlo(), которая должна вывести в консоль сначала 'hello', потом 'EHLO' А теперь код теста:
from hello.hello import say_hello_ehlo
from ehlo.ehlo import say_ehlo
from nose.tools import assert_true
from mock import patch


def test_say_hello_ehlo_mock():
    with patch('ehlo.ehlo.say_ehlo') as ehlo_mock:
        ehlo_mock.return_value = True
        assert_true(say_hello_ehlo())
По замыслу say_ehlo() заменяется на MagicMock(), оригинальная say_ehlo в этом случае вызываться не должна. Проверим:
$ PYTHONPATH=`pwd` nosetests -s test_hello.py
hello
EHLO
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
То есть замена say_ehlo() на mock не произведена, исполнилась оригинальная say_ehlo(), поэтому вы видим в выхлопе EHLO, а его там быть не должно.

ЧЯДНТ?

Camel ★★★★★ ()
Ответ на: Пример. от Camel

Re: Пример.

Как вариант:

    with patch('ehlo.ehlo.say_ehlo') as ehlo_mock:
        from hello.hello import say_hello_ehlo
        ehlo_mock.return_value = True
        assert_true(say_hello_ehlo())
anonymous ()
Ответ на: комментарий от Novel

Всё равно не патчит.

def test_say_hello_hello_mock():
    with patch('hello.hello.say_ehlo') as ehlo_mock:
        ehlo_mock.return_value = True
        assert_true(say_hello_ehlo())


def test_say_ehlo_ehlo_mock():
    with patch('ehlo.ehlo.say_ehlo') as ehlo_mock:
        ehlo_mock.return_value = True
        assert_true(say_hello_ehlo())

В выхлопе всё равно hello и EHLO в обоих случаях.

Camel ★★★★★ ()
Ответ на: Всё равно не патчит. от Camel

странно, у меня все работает.

(17:42) novel@dev:~/tmp/mck1 %> ls
ehlo           hello          test_hello.py  test_hello.pyc
(17:42) novel@dev:~/tmp/mck1 %> PYTHONPATH=`pwd` nosetests -s test_hello.py
hello
<MagicMock name='say_ehlo' id='34445430864'>
.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK
(17:42) novel@dev:~/tmp/mck1 %> cat test_hello.py
from hello.hello import say_hello_ehlo
from ehlo.ehlo import say_ehlo
from nose.tools import assert_true
from mock import patch


def test_say_hello_ehlo_mock():
    with patch('hello.hello.say_ehlo') as ehlo_mock:
        ehlo_mock.return_value = True
        assert_true(say_hello_ehlo())
(17:42) novel@dev:~/tmp/mck1 %>
Novel ★★★★ ()
Ответ на: комментарий от Novel

Для полноты картины.

Можно для полноты картины попросить ещё выхлоп cat hello/hello.py, cat ehlo/ehlo.py и версию mock'а (in before: у меня 1.0.1).

Camel ★★★★★ ()
Ответ на: Для полноты картины. от Camel
(17:54) novel@dev:~/tmp/mck1 %> cat ehlo/ehlo.py

def say_ehlo():
    print 'EHLO'
    return False

(17:54) novel@dev:~/tmp/mck1 %> cat hello/hello.py
from ehlo.ehlo import say_ehlo


def say_hello():
    print 'hello'
    return True


def say_hello_ehlo():
    say_hello()
    print say_ehlo
    say_ehlo()
    return True
(17:54) novel@dev:~/tmp/mck1 %> pip show mock
---
Name: mock
Version: 1.0.1
Location: /usr/local/lib/python2.7/site-packages
Requires:
(17:54) novel@dev:~/tmp/mck1 %>
Novel ★★★★ ()
Ответ на: Для полноты картины. от Camel

Re: Для полноты картины.

Работает и на Python 3.3.4, кстати. Использую unittest.mock из коробки. Код тот же, только для принтов скобочки добавил.

anonymous ()
Ответ на: комментарий от Novel

virtualenv

Вы всё это запускали в virtualenv'е или без такового?

Camel ★★★★★ ()
Ответ на: комментарий от Novel

__init__.py решает.

Перекладывал файлики чтобы выложить всё архивом красивенько, обнаружил что patch заработал, замокал всё как надо. А разгадка оказалась в наличии файла __init__.py в корне. Скажите, где поболее почитать про namespace'ы, import и __init__.py?

Camel ★★★★★ ()
Ответ на: комментарий от Novel

Не везде.

__init__.py я подложил себе везде, да.

А вот оказалось, что подкладывать надо не везде. Если в корне положить, что patch не mock'ает.

Camel ★★★★★ ()
Ответ на: Не везде. от Camel

А вот оказалось, что подкладывать надо не везде. Если в корне положить, что patch не mock'ает.

везде == в ehlo и в hello

Novel ★★★★ ()
Ответ на: комментарий от Novel

where to patch.

Важный момент, собственно из-за непонимания которого и возник этот вопрос: при использовании patch'а нужно указывать путь не до того места где заменяемая функция/класс определяется, но до того места где используется. Без этого ничего не заработает.

Camel ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.