2015-01-21 4 views
0

У меня есть класс:Как мне высмеять класс в модульном тесте Python?

class A: 
    __init__(self): 
     self.b = B() 

    def is_authorized(self) 
     name = self.b.get_name() 

     if name == 'admin': 
      return True 
     else: 
      return False 

я хотел бы написать модульный тест для тестирования методы is_authorized. Проблема в том, что для этого требуется экземпляр класса B, который очень сложно построить изолированно, поскольку для этого требуются сетевые подключения и другие материалы. Как я могу издеваться над этим классом и предоставить то, что имеет только метод get_name. Так что я могу создать класс A и протестировать метод.

ответ

0

Использование библиотеки mock вы можете исправить B класс и заменить его на объект MagicMock(). Библиотека mock была разработана именно для того, чтобы делать подобные работы и ломать тяжелые зависимости от проблемного объекта или реальных ресурсов.

В вашем простом примере полный тест будет:

module_a.py

class B(): 
    def __init__(self): 
     print("The awful B class!!!") 

    def get_name(self): 
     print("The awful B.get_name() method!!!") 


class A(): 
    def __init__(self): 
     self.b = B() 

    def is_authorized(self): 
     name = self.b.get_name() 
     if name == 'admin': 
      return True 
     else: 
      return False 

module_a_test.py

import unittest 
from unittest.mock import patch 
from module_a import A 


class MyTestCase(unittest.TestCase): 

    #patch B class in a_module by a MagicMock instance mock_b_costructor passed to test method 
    @patch("module_a.B") 
    def test_a(self, mock_b_costructor): 
     #B() return value will be the B() instance assigned to a.b property 
     mock_b = mock_b_costructor.return_value 
     # Now start test: 
     a = A() 
     #ok! b is our mock... 
     self.assertIs(a.b, mock_b) 
     #not authorized 
     self.assertFalse(a.is_authorized()) 
     mock_b.get_name.return_value = 'admin' 
     #Yeah!!! we are admin 
     self.assertTrue(a.is_authorized()) 
     #sanity check 
     mock_b.get_name.return_value = 'guest' 
     self.assertFalse(a.is_authorized()) 

Patch будет жить только для метода испытаний контекст. Это простой и простой пример использования mocks и патчей от mock, но реальные случаи могут быть немного сложнее.

0

Создать макет класс для B, например:

class MockB(object): 
    def get_name(self): 
     return 'admin' 

Затем в тестовом случае, завернуть в классе, который inits с MockB вместо регулярной B:

class TestA(A): 
    def __init__(self): 
     self.b = MockB() 

Хотя, честно говоря, я не уверен, что это доказывает.

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