3

I'm new to Python, but I've done quite a bit of unit testing in C# and JavaScript. I'm having trouble figuring out the mocking framework in Python. Here's what I have (trimmed down):

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")

The test fails with

AssertionError: Expected 'get' to be called once. Called 0 times.

The print statement in update_invoice_statuses gets hit, though, because I see the output of

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

Any idea what I'm doing wrong here?

Edit: After @chepner's help, I ran into another assertion error and realized it was because I should be using invoiceRepoMock.get.return_value = None rather than .return_value(None)

asked Jun 3, 2016 at 13:12

1 Answer 1

7

The mock arguments to your test function are swapped. The inner decorator (for the logger) is applied first, so the mock logger should be the first argument to your method.

@mock.patch("ims.business.invoice_business.invoiceRepository")
@mock.patch("ims.business.invoice_business.logger")
def test_invoiceDoesNotExist_logsErrorAndContinues(self, loggerMock, invoiceRepoMock):
 ...
answered Jun 3, 2016 at 13:39
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, that fixed it! I don't think I would have ever noticed that.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.