Python unable to mock function call from test class

Question:

I am trying to mock a bigtable call in my unit test by declaring fixtures like so:

@pytest.fixture()
def bigtableMock():
    bigtableMock = Mock(spec=google.cloud.bigtable.table.Table)
    yield bigtableMock

@pytest.fixture()
def bigtableInstanceMock(bigtableMock):
    bigtableInstanceMock = Mock(spec=google.cloud.bigtable.instance.Instance)
    bigtableInstanceMockAttrs = {'table': bigtableMock}
    bigtableInstanceMock.configure_mock(**bigtableInstanceMockAttrs)
    yield bigtableInstanceMock

@pytest.fixture()
def myDao(bigtableInstanceMock):
    yield MyDao(bigtableInstanceMock)

I mock the read_rows function like so:

def mockReadRowsFuncWith1Dto(testDto):
    mockTableRowData = {}
    mockTableRowData['columnFamily'] = asDict(testDto)
    rowDataMock = MagicMock()
    rowDataMock.__iter__.return_value = [mockTableRowData]
    rowDataMock.__len__ = 1
    def mockReadRowsFunc(startKey, endKey, limit, end_inclusive):
        return rowDataMock

    return mockReadRowsFunc

When I call my test function:

def test_read_table(
   myDao,
   testDto,
   bigtableMock
):
    bigtableMock.read_rows = mockReadRowsFuncWith1Dto(testDto)
    samp = bigtableMock.read_rows(
        startKey="asdf",
        endKey="sadf",
        limit=1,
        end_inclusive=True
        )
    print(f"test data {samp}")
    myDao.readTable(...)

Inside myDao.readTable I call read_rows like so:

tableRows: PartialRowData = self.table.read_rows(
            start_key=startKey,
            end_key=endKey,
            limit=10,
            end_inclusive=True
        )

However, I do not get the magicMock return that I expect inside readTable, tableRows:<Mock name='mock.table().read_rows()' id='4378752480'>, whereas in the test function I can print out the Magic mock: test data <MagicMock id='4413191168'>. Regardless of the print statement or not, I can never invoke the correct mocked read_rows function. What am I doing wrong?

Asked By: Niru

||

Answers:

The problem in my case was that the fixture for bigtableMock was different between test_read_table and the fixture for myDao. I modified my test cases to include the table mocking inside the bigtableMock like so:

@pytest.fixture(read_row_data, mock_append_row)
def bigtableMock():
    bigtableMock = Mock(spec=google.cloud.bigtable.table.Table)
    bigtableMock.read_rows.return_value = [read_row_data]
    bigtableMock.append_row.return_value = mock_append_row
    yield bigtableMock
Answered By: Niru
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.