2015-12-16 2 views
2

У меня есть следующая инструкция в одном из методов модульного теста.Python - Вызываемые вызовы функций

db_employees = self.db._session.query(Employee).filter(Employee.dept == 
    new_employee.dept).all() 

Я хочу, чтобы сотрудники db_employees получили список сотрудников. Я попытался достичь этого, используя:

m = MagickMock() 
m.return_value.filter().all().return_value = employees 

где работники - это список объектов сотрудника. Но это не сработало. Когда я пытаюсь напечатать значение любого атрибута, оно имеет значение mock. Вот как выглядит код:

class Database(object): 
    def __init__(self, user=None, passwd=None, db="sqlite:////tmp/emp.db"): 
     try: 
      engine = create_engine(db) 
     except Exception: 
      raise ValueError("Database '%s' does not exist." % db) 

     def on_connect(conn, record): 
      conn.execute('pragma foreign_keys=ON') 

     if 'sqlite://' in db: 
      event.listen(engine, 'connect', on_connect) 
     Base.metadata.bind = engine 
     DBSession = sessionmaker(bind=engine) 
     self._session = DBSession() 


class TestEmployee(MyEmployee): 
    def setUp(self): 
     self.db = emp.database.Database(db=options.connection) 
     self.db._session._autoflush() 

    @mock.patch.object(session.Session, 'add')  
    @mock.patch.object(session.Session, 'query') 
    def test_update(self, mock_query, mock_add): 
     employees = [{'id': 1, 
         'name': 'Pradeep', 
         'department': 'IT', 
         'manager': 'John'}] 
     mock_add.side_effect = self.add_side_effect 
     mock_query.return_value = self.query_results() 
     self.update_employees(employees) 

    def add_side_effect(self, instance, _warn=True): 
     // Code to mock add 
     // Values will be stored in a dict which will be used to 
     // check with expected value. 

    def query_results(self): 
     m = MagicMock() 
     if self.count == 0: 
      m.return_value.filter.return_value.all.return_value = [employee] 
     elif: 
      m.return_value.filter.return_value.all.return_value = [department] 
     return m 

У меня есть query_results как метод под запрос тестовых запросов дважды. Сначала таблицу сотрудников и следующую таблицу отделов.

Как мне высмеять этот цепной вызов функции?

+0

Прежде всего заменить 'm.return_value.filter ...' 'по m.filter ... 'потому что' m' уже задано как возвращаемое значение 'query'. И добавьте к вашему вопросу, что 'mock_query.mock_calls' пуст. Насколько я понимаю, вы исправляете неправильный объект. –

+0

Теперь попробуйте использовать '@ mock.patch (__ name__ + '.DBSession.query')' для исправления запроса. –

ответ

0

Вы должны исправить query() метод _session 's Database и настроить его, чтобы дать правильный ответ. Вы можете сделать это во многом, но ИМХО - более чистый способ - установить статическую ссылку DBSession's query. Я не знаю, из модуля ведьмы вы импортировали DBSession, поэтому я буду исправлять локальную ссылку.

Другой аспект - это макет конфигурации: мы установим возвращаемое значение query, которое в вашем случае станет объектом, который имеет метод filter().

class TestEmployee(MyEmployee): 
    def setUp(self): 
     self.db = emp.database.Database(db=options.connection) 
     self.db._session._autoflush() 
     self.log_add = {} 

    @mock.patch.object(__name__.'DBSession.add')  
    @mock.patch.object(__name__.'DBSession.query') 
    def test_update(self, mock_query, mock_add): 
     employees = [{'id': 1, 
         'name': 'Pradeep', 
         'department': 'IT', 
         'manager': 'John'}] 
     mock_add.side_effect = self.add_side_effect 
     mock_query.return_value = self.query_results() 
     self.update_employees(employees) 
     .... your test here 

    def add_side_effect(self, instance, _warn=True): 
     # ... storing data 
     self.log_add[...] = [...] 

    def query_results(self): 
     m = MagicMock() 
     value = "[department]" 
     if not self.count: 
      value = "[employee]" 
     m.filter.return_value.all.return_value = value 
     return m 
+0

Это сработало. Изменен mock_query.return_value для mock_query.side_effect = self.query_results. Теперь я могу получить объекты, как ожидалось. Я принимаю ваш ответ, так как это помогло мне разрешить вызов цепочки функций. – Pradeep

0

Я нашел решение аналогичной задачи, где мне нужно, чтобы дразнить из вложенного набора фильтрации вызовов.

Данный код тестируемой похож на следующее:

interesting_cats = (session.query(Cats) 
          .filter(Cat.fur_type == 'furry') 
          .filter(Cat.voice == 'meowrific') 
          .filter(Cat.color == 'orande') 
          .all()) 

Вы можете настроить издевается, как в следующем:

mock_session_response = MagicMock() 
# This is the magic - create a mock loop 
mock_session_response.filter.return_value = mock_session_response 
# We can exit the loop with a call to 'all' 
mock_session_response.all.return_value = provided_cats 

mock_session = MagicMock(spec=Session) 
mock_session.query.return_value = mock_session_response 
Смежные вопросы