My pytest unit test keeps returning the error ModuleNotFoundError: No module name billing
.
Oddly enough the send_invoices
method in the billing module is able to be called when I remove the patch statement. Why is mock.patch unable to find the billing module and patch the method if this is the case?
billing.py
import pdfkit
from django.template.loader import render_to_string
from django.core.mail import EmailMessage
from projectxapp.models import User
Class Billing:
#creates a pdf of invoice. Takes an invoice dictionary
def create_invoice_pdf(self, invoice, user_id):
#get the html of the invoice
file_path ='/{}-{}.pdf'.format(user_id, invoice['billing_period'])
invoice_html = render_to_string('templates/invoice.html', invoice)
pdf = pdfkit.from_file(invoice_html, file_path)
return file_path, pdf
#sends invoice to customer
def send_invoices(self, invoices):
for user_id, invoice in invoices.items():
#get customers email
email = User.objects.get(id=user_id).email
billing_period = invoice['billing_period']
invoice_pdf = self.create_invoice_pdf(invoice, user_id)
email = EmailMessage(
'Statement of credit: {}-{}'.format(user_id, billing_period),
'Attached is your statement of credit.\
This may also be viewed on your dashboard when you login.',
'[email protected]',
[email],
).attach(invoice_pdf)
email.send(fail_silently=False)
return True
test.py
from mock import patch
from projectxapp import billing
@pytest.mark.django_db
def test_send_invoice():
invoices = {
1: {
'transaction_processing_fee': 2.00,
'service_fee': 10.00,
'billing_period': '2020-01-02'
},
2: {
'transaction_processing_fee': 4.00,
'service_fee': 20.00,
'billing_period': '2020-01-02'
}
}
with patch('services.billing.Billing().create_invoice_pdf') as p1:
p1.return_value = '/invoice.pdf'
test = billing.Billing().send_invoices(invoices)
assert test == True
Since I had already imported the module of the method I needed to patch. I didn't need to use the full path including the package name.
Changed
patch('projectxapp.billing.Billing.create_invoice_pdf')
to this
patch('billing.Billing.create_invoice_pdf')
From the unittest documentation:
target should be a string in the form 'package.module.ClassName'. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch() from. The target is imported when the decorated function is executed, not at decoration time.