2017-02-16 4 views
1

У меня есть модуль, который отвечает за выбор метода обратного вызова. Я хочу издеваться над методом choice, но, несмотря на то, что это похоже на то, что он насмехается, он все равно возвращает случайные результаты (иногда тесты проходят и иногда терпят неудачу). В чем причина этого недетерминированного поведения?Mocking callbacks - странное поведение

decision.py:

from numpy.random.mtrand import choice 

class RandomDecision: 

    def __init__(self, f_bet, f_call, f_fold): 
     bet, call, fold = 0.15, 0.50, 0.35 
     self.propabilities = [bet, call, fold] 
     self.choices = [f_bet, f_call, f_fold] 

    def decide(self, player=None, information=None): 
     decision = choice(self.choices, 1, p=self.propabilities)[0] 
     args =() 
     if decision == self.f_bet: 
      args = self._get_random_bet(information, player), 
     decision(*args) 

    # some more methods... 

Теперь давайте попробуем протестировать его

test_decisions.py

from unittest.mock import Mock, patch 
from decision import RandomDecision 

class TestRandomDecisions(unittest.TestCase): 

def setUp(self): 
    self.fold = Mock() 
    self.call = Mock() 
    self.bet = Mock() 
    self.rand_decision = RandomDecision(f_fold=self.fold, 
             f_call=self.call, 
             f_bet=self.bet) 

def test_call(self): 
    bet = 40 
    with patch('numpy.random.mtrand.choice', side_effect=[self.call]),\ 
     patch('decision.RandomDecision._get_random_bet', 
       return_value=bet): 
     self.rand_decision.decide(Mock(), None) 
     self.assertTrue(self.call.called) 
+0

Да, 'patch' и' from' импорт не играют хорошо вместе. Если вы хотите «исправить» его, вероятно, лучше не «импортировать» его. – user2357112

ответ

0

У меня была точно такая же проблема, когда я начал играть с patch. Проблема в том, что это утверждение делает что-то слегка подлый.

from numpy.random.mtrand import choice 

Он копирует атрибут choice из numpy.random.mtrand модуля к decision модуля. Когда вы вызываете choice() с модуля decision, вы используете локальную копию вместо оригинала.

Ваш тест насмехается над оригиналом, а ваш код использует его локальную копию, поэтому он не использует макетную версию.

Если вы меняете patch('numpy.random.mtrand.choice', side_effect=[self.call]) на patch('decision.choice', side_effect=[self.call]), он должен работать.

+0

Вот и все, это работает как шарм! Также стоит признать, что я допустил ошибку и должен был изменить 'side_effect' на' return_value', поэтому это будет 'patch ('decision.choice', return_value = [self.call])'. Спасибо за помощь. – user2817340

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