from django.test import TestCase, override_settings, Client import requests from unittest import mock from django.conf import settings from mpesa_api.util.mpesautils import get_token from mpesa_api.core.models import B2CRequest, OnlineCheckout from mpesa_api.core.mpesa import Mpesa from mpesa_api.core import tasks from mpesa_api.util import mocks from mpesa_api.util.b2cutils import send_b2c_request from mpesa_api.util.c2butils import register_c2b_url, process_online_checkout from django.urls import reverse from mpesa_api.core import signals from django.db.models.signals import post_save from mpesa_api.core.tasks import process_b2c_call_response_task, send_b2c_request_task, \ call_online_checkout_task, handle_online_checkout_response_task from celery import chain class MockResponse: """ MockResponse Class """ def __init__(self, json_data, status_code): self.json_data = json_data self.status_code = status_code def json(self): return self.json_data def mock_requests_get(*args, **kwargs): """ Mock requests get :param args: :param kwargs: :return: """ url = kwargs['url'] if url == settings.GENERATE_TOKEN_URL: return MockResponse(mocks.SUCCESS_TOKEN_REQUEST, 200) def mock_requests_post(*args, **kwargs): """ Mock requests post :param args: :param kwargs: :return: """ url = kwargs['url'] if url == settings.B2C_URL: return MockResponse(mocks.SUCCESS_B2C_SEND_RESPONSE, 200) elif url == settings.C2B_REGISTER_URL: return MockResponse(mocks.REGISTER_URL_SUCCESS, 200) elif url == settings.C2B_ONLINE_CHECKOUT_URL: return MockResponse(mocks.ONLINE_REQUEST_RESPONSE, 200) def post(url, data): c = Client() response = c.post(url, data) return response.content.decode('utf-8') class FetchTokenTest(TestCase): """ Fetch Token Test """ @mock.patch('requests.get', side_effect=mock_requests_get) def test_token_is_fetched_as_expected(self, mock_get): response = get_token('c2b') self.assertEqual(response, mocks.SUCCESS_TOKEN_REQUEST) self.assertTrue(mock_get.called) @mock.patch('requests.get', side_effect=mock_requests_get) @mock.patch('requests.post', side_effect=mock_requests_post) @override_settings(CELERY_ALWAYS_EAGER=True) class B2CMethodsTest(TestCase): def setUp(self): self.req = Mpesa.b2c_request(phone=254708374149, amount=100.0) def test_successful_b2c_request(self, mock_post, mock_get): response = send_b2c_request(int(self.req.amount), self.req.phone, self.req.id) self.assertEqual(response, mocks.SUCCESS_B2C_SEND_RESPONSE) self.assertTrue(mock_post.called) def test_failed_b2c_request(self, mock_post, mock_get): response = send_b2c_request(int(self.req.amount), self.req.phone, self.req.id) response = mocks.FAILED_B2C_SEND_RESPONSE self.assertEqual(response, mocks.FAILED_B2C_SEND_RESPONSE) self.assertTrue(mock_post.called) def test_b2c_result_url(self, mock_post, mock_get): url = reverse('mpesa:b2c_result') response = post(url, mocks.B2C_SUCCESSFUL_RESULT) self.assertEqual('{"value":"ok","key":"status","detail":"success"}', response) def test_b2c_timeout_url(self, mock_post, mock_get): url = reverse('mpesa:b2c_timeout') response = post(url, mocks.B2C_SUCCESSFUL_RESULT) self.assertEqual('{"value":"ok","key":"status","detail":"success"}', response) @mock.patch('mpesa_api.core.signals.handle_b2c_request_post_save', autospec=True) def test_b2c__post_save_signal(self, mock_signal, mock_post, mock_get): post_save.connect(mock_signal, sender=B2CRequest, dispatch_uid='test_b2c_request_post_save') Mpesa.b2c_request(phone=254708374149, amount=100.0) self.assertEquals(mock_signal.call_count, 1) post_save.disconnect(mock_signal, sender=B2CRequest, dispatch_uid='test_b2c_request_post_save') def test_b2c_tasks(self, mock_post, mock_get): self.assertTrue(chain(send_b2c_request_task.s(100, 254708374149, 1), process_b2c_call_response_task.s(1)).apply_async()) def tearDown(self): post_save.connect(signals.handle_b2c_request_post_save, sender=B2CRequest) @mock.patch('requests.get', side_effect=mock_requests_get) @mock.patch('requests.post', side_effect=mock_requests_post) @override_settings(CELERY_ALWAYS_EAGER=True) class C2BMethodTest(TestCase): def test_register_c2b_url(self, mock_post, mock_get): response = Mpesa.c2b_register_url() self.assertEqual(mocks.REGISTER_URL_SUCCESS, response) def setUp(self): self.request = Mpesa.stk_push(phone=254708374149, amount=100.0, account_reference='Test') def test_successful_online_checkout_response(self, mock_post, mock_get): resp = process_online_checkout(self.request.phone, int(self.request.amount), 'Test', 'test') self.assertEqual(mocks.ONLINE_REQUEST_RESPONSE, resp) def test_success_online_checkout_url(self, mock_post, mock_get): url = reverse('mpesa:c2b_checkout_callback') response = post(url, mocks.ONLINE_SUCCESS_RESPONSE) self.assertEqual('{"value":"ok","key":"status","detail":"success"}', response) def test_validation_url(self, mock_post, mock_get): url = reverse('mpesa:c2b_validation') response = post(url, mocks.PAYBILL_RESPONSE) self.assertEqual('{"value":"ok","key":"status","detail":"success"}', response) def test_confirmation_url(self, mock_post, mock_get): url = reverse('mpesa:c2b_confirmation') response = post(url, mocks.PAYBILL_RESPONSE) self.assertEqual('{"value":"ok","key":"status","detail":"success"}', response) @mock.patch('mpesa_api.core.signals.handle_online_checkout_post_save', autospec=True) def test_c2b_post_save_signal(self, mock_signal, mock_post, mock_get): post_save.connect(mock_signal, sender=OnlineCheckout, dispatch_uid='test_online_request_post_save') Mpesa.stk_push(phone=254708374149, amount=100.0, account_reference='Test') self.assertEquals(mock_signal.call_count, 1) post_save.disconnect(mock_signal, sender=OnlineCheckout, dispatch_uid='test_online_request_post_save') def test_online_tasks(self, mock_post, mock_get): self.assertTrue( chain(call_online_checkout_task.s(254708374149, 100, '', ''), handle_online_checkout_response_task.s(1)).apply_async()) def tearDown(self): post_save.connect(signals.handle_online_checkout_post_save, sender=OnlineCheckout)