Testing
Test your Paystack integration thoroughly.
Unit Testing
Test individual API methods:
from django.test import TestCase
from unittest.mock import patch, MagicMock
from djpaystack.api.transactions import Transaction
class TransactionTestCase(TestCase):
def setUp(self):
self.transaction = Transaction()
@patch('djpaystack.api.transactions.requests.post')
def test_initialize_transaction(self, mock_post):
# Mock API response
mock_post.return_value.json.return_value = {
'status': True,
'message': 'Authorization URL created',
'data': {
'authorization_url': 'https://checkout.paystack.com/...',
'access_code': 'ACCESS_CODE',
'reference': 'UNIQUE_REF',
}
}
response = self.transaction.initialize(
email='test@example.com',
amount=50000
)
self.assertTrue(response['status'])
self.assertIn('authorization_url', response['data'])
@patch('djpaystack.api.transactions.requests.get')
def test_verify_transaction(self, mock_get):
# Mock API response
mock_get.return_value.json.return_value = {
'status': True,
'data': {
'reference': 'UNIQUE_REF',
'amount': 50000,
'status': 'success',
}
}
response = self.transaction.verify('UNIQUE_REF')
self.assertTrue(response['status'])
self.assertEqual(response['data']['status'], 'success')
Integration Testing
Test with real API (use test credentials):
from django.test import TestCase, override_settings
from djpaystack.api.transactions import Transaction
@override_settings(PAYSTACK={
'SECRET_KEY': 'sk_test_...',
'PUBLIC_KEY': 'pk_test_...',
})
class IntegrationTestCase(TestCase):
def test_payment_flow(self):
"""Test complete payment flow"""
transaction = Transaction()
# Initialize
init_response = transaction.initialize(
email='test@example.com',
amount=50000
)
self.assertTrue(init_response['status'])
reference = init_response['data']['reference']
# Note: In real testing, user would complete payment
# Then verify
verify_response = transaction.verify(reference)
# Results depends on whether payment was completed
View Testing
Test your payment views:
from django.test import TestCase, Client
from unittest.mock import patch
class PaymentViewTestCase(TestCase):
def setUp(self):
self.client = Client()
@patch('myapp.views.Transaction.initialize')
def test_checkout_view(self, mock_initialize):
mock_initialize.return_value = {
'status': True,
'data': {
'authorization_url': 'https://checkout.paystack.com/...',
'reference': 'TEST_REF',
}
}
response = self.client.post('/checkout/', {
'email': 'test@example.com',
'amount': '500',
})
self.assertEqual(response.status_code, 302) # Redirect
Webhook Testing
Test webhook handling:
from django.test import TestCase, Client
from django.urls import reverse
import json
from unittest.mock import patch
class WebhookTestCase(TestCase):
def setUp(self):
self.client = Client()
self.webhook_url = reverse('paystack-webhook')
@patch('djpaystack.webhooks.handlers.verify_webhook_signature')
def test_charge_success_webhook(self, mock_verify):
mock_verify.return_value = True
payload = {
'event': 'charge.success',
'data': {
'reference': 'TEST_REF',
'amount': 50000,
'customer': {'email': 'test@example.com'},
'status': 'success',
}
}
response = self.client.post(
self.webhook_url,
data=json.dumps(payload),
content_type='application/json'
)
self.assertEqual(response.status_code, 200)
Testing Utilities
Use the built-in test utilities:
from djpaystack.dev.webhook_tester import WebhookTester
from djpaystack.dev.mock_client import MockPaystackClient
# Test webhooks
tester = WebhookTester()
tester.test_charge_success({
'reference': 'test-123',
'amount': 50000,
})
# Mock client for testing
mock_client = MockPaystackClient()
response = mock_client.initialize(
email='test@example.com',
amount=50000
)
Best Practices
Use test credentials, never live keys
Mock external API calls
Test both success and failure cases
Test error handling
Use factories for test data
Keep tests isolated
Test at multiple levels (unit, integration, end-to-end)
import factory
from djpaystack.models import Transaction
class TransactionFactory(factory.django.DjangoModelFactory):
class Meta:
model = Transaction
reference = factory.Sequence(lambda n: f'TEST_REF_{n}')
amount = 50000
customer_email = 'test@example.com'
status = 'pending'