2015-11-11 4 views
1

Короче говоря, я отлично умею издеваться над методом класса, когда это только тот метод, который заменяется макетным объектом, но я не могу издеваться над этим методом, когда пытаюсь заменить целое класс от макета объектаОтказывание целого класса

@mock.patch.object успешно издевается над методом scan, но @mock.patch не может этого сделать. Я следовал примеру на https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch , но, видимо, я делаю что-то неправильно.

Я насмешливо модуль лексикон в том же пространстве имен в обоих случаях (это импортируется import lexicon в sentence_parser), но mock_lexicon is lexicon.lexicon проверка неудачна

#!python 
import sys; 
sys.path.append('D:\python\lexicon'); 
import lexicon; 

import sentence_parser; 
import unittest2 as unittest; 
import mock; 

class ParserTestCases(unittest.TestCase) : 

    def setUp(self) : 
     self.Parser = sentence_parser.Parser(); 

    @mock.patch('lexicon.lexicon') 
    def test_categorizedWordsAreAssigned_v1(self, mock_lexicon) : 

     print "mock is lexicon:"; 
     print mock_lexicon is lexicon.lexicon + "\n"; 

     instance = mock_lexicon.return_value; 
     instance.scan.return_value = "anything";  

     self.Parser.categorize_words_in_sentence("sentence"); 
     instance.scan.assert_called_once_with("sentence"); 

    @mock.patch.object(lexicon.lexicon, 'scan') 
    def test_categorizedWordsAreAssigned_v2(self, mock_scan) : 

     mock_scan.return_value = "anything";  

     self.Parser.categorize_words_in_sentence("sentence"); 
     mock_scan.assert_called_once_with("sentence"); 

if (__name__ == '__main__') : 
    unittest.main() 

Выход:

mock is lexicon: 
False 

====================================================================== 
FAIL: test_categorizedWordsAreAssigned_v1 (__main__.ParserTestCases) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "D:\python\get_img\getImage_env\lib\site-packages\mock\mock.py", line 1305, in patched 
    return func(*args, **keywargs) 
    File "./test_sentence_parser.py", line 26, in test_categorizedWordsAreAssigned_v1 
    instance.scan.assert_called_once_with("sentence"); 
    File "D:\python\get_img\getImage_env\lib\site-packages\mock\mock.py", line 947, in assert_called_once_with 
    raise AssertionError(msg) 
AssertionError: Expected 'scan' to be called once. Called 0 times. 

---------------------------------------------------------------------- 
Ran 2 tests in 0.009s 

FAILED (failures=1) 

EDIT:

Для уточнения, Parser определяется следующим образом:

#!python 

import sys; 
sys.path.append('D:\python\lexicon'); 
import lexicon; 

class Parser(object) : 

    my_lexicon = lexicon.lexicon() 

    def __init__(self) : 
     self.categorized_words = ['test']; 

    def categorize_words_in_sentence(self, sentence) : 
     self.categorized_words = self.my_lexicon.scan(sentence); 


if (__name__ == '__main__') : 
    instance = Parser(); 
    instance.categorize_words_in_sentence("bear"); 
    print instance.categorized_words; 
+0

Три вопроса: 1) Я посмотрел на 'модуль lexicon' на https://github.com/bitprophet/lexicon/tree/master/lexicon и швам мне класс' 'Lexicon' вместо lexicon'; 2) Я предполагаю, что у вас есть еще один модуль 'lexicon', а не только тот, который находится в' D: \ python \ lexicon'; 3) зачем вам нужно ';' в конце строк? –

+0

1) 'lexicon' - мой собственный модуль, который просто имеет то же имя, что и тот, который вы связали; 2) У меня только два файла в 'D: \ python \ lexicon' one -' lexicon.py', а второй - 'test_lexicon.py', содержащий unittests; 3) ';' - это только то, к чему я привык на других языках, но здесь это не так актуально. – krzym1

ответ

1

Что реально Уместно как categorize_words_in_sentenceParser «s метод использования lexicon. Но в первую очередь мы должны удалить шум:

print mock_lexicon is lexicon.lexicon + "\n" 

Это то, что может привести нас к неправильному направлению: попробуйте заменить его

self.assertIs(mock_lexicon, lexicon.lexicon) 

и вы поймете, что вы печатаете False потому mock_lexicon нет lexicon.lexicon + "\n" но только lexicon.lexicon.

Теперь я не могу вам сказать, почему первый тест не работает, потому что ответ в categorize_words_in_sentence метод или более вероятно, в sentence_parser модуле, где я могу догадаться, что вы можете иметь что-то вроде

from lexicon import lexicon 

В обоих случаях принять посмотрите на документацию Where to Patch, которая может просветить вас о том, что может быть причиной и что вам действительно нужно запланировать в вашем случае.

Вторая версия работает только потому, что вы исправляете объект, а не ссылку (это должно быть иначе).

Наконец более кратким и общая версия может быть:

@mock.patch('lexicon.lexicon.scan', return_value="anything") 
def test_categorizedWordsAreAssigned_v3(self, mock_scan) : 
    self.Parser.categorize_words_in_sentence("sentence") 
    mock_scan.assert_called_once_with("sentence") 

Еще одна вещь: удалить unittest2 по крайней мере, вы не используете Python 2.4, и вы заинтересованы в портированном UnitTest особенностей.

[EDIT]

Теперь я могу остановиться, чтобы угадать и точка вам, почему первая версия не работает и никогда не будет работать:

class Parser(object) : 
    my_lexicon = lexicon.lexicon() 

Parser.my_lexicon атрибут оценивается в время загрузки. Это означает, что при импорте sentence_parser создается lexicon и ссылка, связанная с Parser.my_lexicon. Когда вы устанавливаете lexicon.lexicon, вы оставляете эту ссылку нетронутой, и ваш объект парсера по-прежнему использует исходную ссылку, созданную при импорте.

Что вы можете сделать, это исправить ссылку в Parser классе по

@patch("sentence_parser.Parser.my_lexicon") 

Вы можете использовать create_autospect, если вы хотите дать вашему макет то же lexicon «s подписи.

@patch("sentence_parser.Parser.my_lexicon", create_autospec("lexicon.lexicon", instance=True)) 
+0

В первоначальном посте я указал, что лексика импортируется просто «import lexicon;». Я добавил полный код «Parser» к исходному сообщению. Я видел «Где патч». Я знаю, что может издеваться только над методом «scan», но меня раздражает то, что насмехается весь класс, не работает, когда нет причин для этого не для – krzym1

+0

Обновлено ... Класс кода Parser был тем, что действительно актуально здесь , –

+0

Спасибо! Он наконец работает. Мне нужно прочитать ссылки на python, я надеялся, что такие неприятности будут упомянуты в документации Where to Patch. – krzym1

Смежные вопросы