5

我的 pytest 单元测试不断返回错误 ModuleNotFoundError: No module name billing

奇怪的send_invoices是,当我删除补丁语句时,可以调用计费模块中的方法。如果是这种情况,为什么 mock.patch 无法找到计费模块并修补方法?

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.',
                'no-reply@trevoe.com',
                [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
4

3 回答 3

5

当您使用patch. 另外,不要在路径中使用括号。修改对象的return_value属性,Mock自定义调用对象的返回值:

with patch('projectxapp.billing.Billing.create_invoice_pdf') as p1:
    p1.return_value = '/invoice.pdf'
    test = billing.Billing().send_invoices(invoices)
于 2020-04-05T14:28:03.677 回答
0

解决方案

由于我已经导入了我需要修补的方法的模块。我不需要使用包含包名的完整路径。

改变了

patch('projectxapp.billing.Billing.create_invoice_pdf')

对此

patch('billing.Billing.create_invoice_pdf')

单元测试文档

目标应该是格式为“package.module.ClassName”的字符串。导入目标并将指定对象替换为新对象,因此目标必须可以从您调用 patch() 的环境中导入。目标是在执行装饰函数时导入的,而不是在装饰时。

于 2020-04-27T12:06:13.037 回答
-1

因为,这是第一个带有补丁的 ModuleNotFoundError 谷歌命中......

就我而言,这是字母大小写的问题(com.foo.SftpClient 而不是 com.foo.SFTPClient)

在我的环境(python 3.6)中,解释器抱怨找不到 com.foo 模块,即使实际原因是类名中的拼写错误

于 2021-08-23T13:51:22.823 回答