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

  1. Use test credentials, never live keys

  2. Mock external API calls

  3. Test both success and failure cases

  4. Test error handling

  5. Use factories for test data

  6. Keep tests isolated

  7. 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'