Examples: query, "exact match", wildcard*, wild?ard, wild*rd
Fuzzy search: cake~ (finds cakes, bake)
Term boost: "red velvet"^4, chocolate^2
Field grouping: tags:(+work -"fun-stuff")
Escape special characters +-&|!(){}[]^"~*?:\ - e.g. \+ \* \!
Range search: properties.timestamp:[1587729413488 TO *] (inclusive), properties.title:{A TO Z}(excluding A and Z)
Combinations: chocolate AND vanilla, chocolate OR vanilla, (chocolate OR vanilla) NOT "vanilla pudding"
Field search: properties.title:"The Title" AND text
 
Answered
Why is monkeypatch failing when attempting to mock a class in a Q2 module?

Some method I am creating requires an instance of GeneratedTransactions to be created. The methods associated with this class are used. Please see the link here for docs on the class I am using: https://docs.q2developer.com/api_references/q2_sdk/db/db_objects/generated_transactions.html?highlight=generatedtransactions#q2_sdk.hq.db.generated_transactions.GeneratedTransactions . My method looks something like this:

from q2_sdk.hq.db.generated_transactions import (
    GeneratedTransactions,
    ExternalGeneratedTransfer,
)

async def _my_method(self, start, end):
  external_generated_transfers = []
        end = end if end is not None else datetime.now()
        generated_transactions = GeneratedTransactions(self.logger, self.hq_credentials)
        i = 1
        while True:
            values = await generated_transactions.get_by_create_date_range(
                start, end, i
            )
            if values is None:
                break
            external_generated_transfers.extend(values)
            i += 1
        return external_generated_transfers

This method now needs to be unit tested. Following the docs on unit testing, I am using monkeypatch to try to achieve this. I want to patch GeneratedTransactions itself so a real instance is not created. An example of a unit test that I am creating is below:

import pytest
from unittest.mock import Mock, patch, AsyncMock
from datetime import datetime, timedelta

# from q2_sdk.tools.testing.decorators import mock_q2_request
from external_transfers_report.entrypoint import EntryPoint
from q2_sdk.hq.db.generated_transactions import GeneratedTransactions


class Mockexternal_transfers_report(EntryPoint):
    def __init__(self):
        super().__init__()
				
class TestMyMethod:
    def setup_method(self):
        self.handler = Mockexternal_transfers_report()

    def teardown_method(self):
        del self.handler

    @pytest.fixture
    def mock_generated_transactions_class(self, monkeypatch):
        class MockGeneratedTransactions:
            async def get_by_create_date_range(self, *args, **kwargs):
                return []

        monkeypatch.setattr(
            "q2_sdk.hq.db.generated_transactions.GeneratedTransactions",
            MockGeneratedTransactions,
        )

    @pytest.mark.asyncio
    async def test_my_method(
        self, mock_generated_transactions_class
    ):
        result = await self.handler._my_method("abc")
        assert not result

The problem that I am having is that the class GeneratedTransactions is not being replaced with a mock implementation. The real instance and get_by_create_date_range are being called. I have tried other ideas such as using the patch decorator inside unittest.mock, and the result is the same.

Oddly, I can patch get_by_create_date_range just fine with a mock. While this is a workable solution in a sense, it doesn't solve the issue of a real instance of GeneratedTransactions being created.

Why is monkeypatch not effective at mocking Q2 classes in this instance?

Votes Newest

Answers


Hey Ethan,

We typically see the monkeypatch setattr implemented a little differently.

This is what you have:

monkeypatch.setattr(
            "q2_sdk.hq.db.generated_transactions.GeneratedTransactions",
            MockGeneratedTransactions,
        )

But we would typically see a function and not a class.

The other approach you could take here is to use the mock_q2_request decorator and mock the data being returned from the calls.

Posted one year ago
Paden Rose
160 × 1 Administrator
116 Views
1 Answer
one year ago
one year ago