bots: tests: Move http mock to context manager.

This commit decouples the http mock conversation
feature from assert_bot_response(), and moves it
to the context manager mock_http_conversation().
This allows a modular design with context managers
that could be added for assert_bot_response().
This commit is contained in:
Robert Hönig 2017-06-08 15:54:28 +02:00 committed by showell
parent a9bb0c9417
commit 01c363317e
2 changed files with 32 additions and 38 deletions

View file

@ -51,10 +51,10 @@ class TestGiphyBot(BotTestCase):
# This message calls `send_reply` function of BotHandlerApi # This message calls `send_reply` function of BotHandlerApi
keyword = "Hello" keyword = "Hello"
gif_url = "https://media4.giphy.com/media/3o6ZtpxSZbQRRnwCKQ/giphy.gif" gif_url = "https://media4.giphy.com/media/3o6ZtpxSZbQRRnwCKQ/giphy.gif"
with self.mock_http_conversation(get_http_request(keyword),
get_http_response_json(gif_url)):
self.assert_bot_response( self.assert_bot_response(
message = {'content': keyword}, message = {'content': keyword},
response = {'content': get_bot_response(gif_url)}, response = {'content': get_bot_response(gif_url)},
expected_method='send_reply', expected_method='send_reply'
http_request=get_http_request(keyword),
http_response=get_http_response_json(gif_url)
) )

View file

@ -17,9 +17,10 @@ from bot_lib import StateHandler
from bots_api import bot_lib from bots_api import bot_lib
from six.moves import zip from six.moves import zip
from contextlib import contextmanager
from unittest import TestCase from unittest import TestCase
from typing import List, Dict, Any, Optional from typing import List, Dict, Any, Optional, Callable
from types import ModuleType from types import ModuleType
current_dir = os.path.dirname(os.path.abspath(__file__)) current_dir = os.path.dirname(os.path.abspath(__file__))
@ -74,40 +75,33 @@ class BotTestCase(TestCase):
else: else:
instance.send_reply.assert_called_with(message, response['content']) instance.send_reply.assert_called_with(message, response['content'])
def assert_bot_response(self, message, response, expected_method, @contextmanager
http_request=None, http_response=None): def mock_http_conversation(self, http_request, http_response):
# type: (Dict[str, Any], Dict[str, Any], str, Optional[Dict[str, Any]], Optional[Dict[str, Any]]) -> None # type: (Dict[str, Any], Dict[str, Any]) -> Any
message_handler = self.get_bot_message_handler() """
# Mocking BotHandlerApi Use this context manager to mock and verify a bot's HTTP
with patch('bots_api.bot_lib.BotHandlerApi') as MockClass: requests to the third-party API (and provide the correct
# If not mock http_request/http_response are provided, third-party API response. This allows us to test things
# just call the request normally (potentially using that would require the Internet without it).
# the Internet) """
if http_response is None: assert http_response is not None and http_request is not None
assert http_request is None
self.call_request(message_handler, message, expected_method,
MockClass, response)
return
# Otherwise, we mock requests, and verify that the bot
# made the correct HTTP request to the third-party API
# (and provide the correct third-party API response.
# This allows us to test things that would require the
# Internet without it).
assert http_request is not None
with patch('requests.get') as mock_get: with patch('requests.get') as mock_get:
mock_result = mock.MagicMock() mock_result = mock.MagicMock()
mock_result.json.return_value = http_response mock_result.json.return_value = http_response
mock_result.ok.return_value = True mock_result.ok.return_value = True
mock_get.return_value = mock_result mock_get.return_value = mock_result
self.call_request(message_handler, message, expected_method, yield
MockClass, response)
# Check if the bot is sending the correct http_request corresponding
# to the given http_response.
if http_request is not None:
mock_get.assert_called_with(http_request['api_url'], mock_get.assert_called_with(http_request['api_url'],
params=http_request['params']) params=http_request['params'])
def assert_bot_response(self, message, response, expected_method):
# type: (Dict[str, Any], Dict[str, Any], str) -> None
message_handler = self.get_bot_message_handler()
# Mocking BotHandlerApi
with patch('bots_api.bot_lib.BotHandlerApi') as MockClass:
self.call_request(message_handler, message, expected_method,
MockClass, response)
def bot_to_run(self, bot_module): def bot_to_run(self, bot_module):
# Returning Any, same argument as in get_bot_message_handler function. # Returning Any, same argument as in get_bot_message_handler function.
# type: (str) -> Any # type: (str) -> Any