Mocks在Python单元测试中没有受到攻击

时间:2016-06-03 13:12:27

标签: python unit-testing mocking

我是Python的新手,但我已经在C#和JavaScript中完成了相当多的单元测试。我在Python中弄清楚模拟框架时遇到了麻烦。这是我的(裁剪):

invoice_business.py

import ims.repository.invoice_repository as invoiceRepository
import logging

logger = logging.getLogger(__name__)

def update_invoice_statuses(invoices):
    for invoice in invoices:
        dbInvoice = invoiceRepository.get(invoice.invoice_id)
        print("dbInvoice is %s" % dbInvoice) #prints <MagicMock etc.>

        if dbInvoice is None:
            logger.error("Unable to update status for invoice %d" % invoice.invoice_id)
            continue;

test_invoice_business.py

from unittest import TestCase, mock
import logging
import ims.business.invoice_business as business

class UpdateInvoiceTests(TestCase):
    @mock.patch("ims.business.invoice_business.invoiceRepository")
    @mock.patch("ims.business.invoice_business.logger")
    def test_invoiceDoesNotExist_logsErrorAndContinues(self, invoiceRepoMock, loggerMock):
        #Arrange
        invoice = Invoice(123)
        invoice.set_status(InvoiceStatus.Filed, None)
        invoiceRepoMock.get.return_value(33)

        #Act
        business.update_invoice_statuses([invoice])

        #Assert
        invoiceRepoMock.get.assert_called_once_with(123)
        loggerMock.error.assert_called_once_with("Unable to update status for invoice 123")

测试失败,

  

AssertionError:预期'get'被调用一次。叫0次。

print中的update_invoice_statuses语句会受到影响,因为我看到

的输出
dbInvoice is <MagicMock name='invoiceRepository.get()' id='xxxx'>

知道我在这里做错了吗?

编辑:在@Chepner的帮助之后,我遇到了另一个断言错误并意识到这是因为我应该使用invoiceRepoMock.get.return_value = None而不是.return_value(None)

1 个答案:

答案 0 :(得分:4)

交换测试函数的模拟参数。首先应用内部装饰器(用于记录器),因此模拟记录器应该是方法的第一个参数。

@mock.patch("ims.business.invoice_business.invoiceRepository")
@mock.patch("ims.business.invoice_business.logger")
def test_invoiceDoesNotExist_logsErrorAndContinues(self, loggerMock, invoiceRepoMock):
    ...