简体   繁体   中英

How to mock a class method that is called from another class with pytest_mock

In the below files I have InternalDogWebhookResource which calls VisitOrchestrator.fetch_visit . I am attempting to write a test for InternalDogWebhookResource but mock VisitOrchestrator.fetch_visit since it is a network call.

I have tried the mock paths:

  • api.dog.handlers.internal.VisitOrchestrator.fetch_visit
  • api.dog.handlers.internal.InternalDogWebhookResource.VisitOrchestrator.fetch_visit
  • api.dog.handlers.internal.InternalDogWebhookResource.fetch_visit

and many others, but I am always getting AssertionError: assert None

I can confirm that the client.post in the test works because when i remove the mock asserts, i get a response back from the api which means fetch_visit is called.

How can I find the mocker.patch path?

api/dog/handlers/internal.py

from api.dog.helpers.visits import VisitOrchestrator

@api.route("/internal/dog/webhook")
class InternalDogWebhookResource():

    def post(self) -> JsonResponse:
        if event_type == EventType.CHANGE:
            VisitOrchestrator.fetch_visit(event['visitId'])

        return JsonResponse(status=204)

api/dog/helpers/visits.py

class VisitOrchestrator:
    @classmethod
    def fetch_visit(cls, visit_id: str) -> VisitModel:
        # do stuff

        return visit

tests/v0/dog/handlers/test_webhook.py

import pytest
from pytest_mock import MockerFixture

from api.dog.handlers.internal import InternalDogWebhookResource, EventType
from tests.v0.utils import url_for


def test_webhook_valid(client, config, mocker: MockerFixture):
    visit_id = '1231231'

    mock_object = mocker.patch(
        'api.dog.handlers.internal.VisitOrchestrator.fetch_visit',
        return_value=visit_id,
    )

    res = client.post(
        url_for(InternalDogWebhookResource),
        json={'blag': 'blargh'}
    )
    assert mock_object.assert_called_once()

You're doing the right things - your second approach is generally the way to go with mocks (mocking api.dog.handlers.internal.InternalDogWebhookResource.VisitOrchestrator.fetch_visit )

I would try to do the minimal test code function:

def test_webhook_valid(mocker):
    mock_fetch_visit = mocker.MagicMock(name='fetch_visit')
    mocker.patch('api.dog.handlers.internal.VisitOrchestrator.fetch_visit',
                 new=mock_fetch_visit)

    InternalDogWebhookResource().post()

    assert 1 == mock_fetch_visit.call_count

If this works for you - maybe the problem is with the client or other settings in your test method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM