python / python/cpython

Unittest Patch only works on attributes, methods

Ouverte
#129,629 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

stdlib type-bug
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

Bug report

Bug description:

I am having an issue where the patch method from the unittest.mock module is only working when I patch attributes of imported modules in other files. I do not understand if this is an issue of my import patterns or a misunderstanding of how patching works. (I am importing the app code before the patch is able to run).

I devised a test to show how the functionality is confusing me:

In my app code I have the following code

    from datetime import date
    ...
    import boto3
    ...
    from common.functions import asodates2datetime
    from core.mixins.usecases import ASOUsecaseTools


    class foo:
        @staticmethod
        @ASOUsecaseTools.get_by_name
        def bar(self, relevant_date):
            client = boto3.client("s3")
            today = date.today()
            date = asodates2datetime(relevant_date)

And from my test code I can patch in the following way:

    @mock.patch("src.aoi.usecases.date")
    @mock.patch("src.aoi.usecases.ASOUsecaseTools.get_by_name")
    @mock.patch("src.aoi.usecases.asodates2datetime")
    @mock.patch("src.aoi.usecases.boto3.client")
    def test_foo_gets_bar(self, m_d, m_g, m_a, m_c):
        m_d.today.return_value = <date>
        m_d.side_effect = lambda *args, **kw: date(*args, **kw)
        # more patching of functions here

However, when the test is run, If I set a breakpoint in the bar function and check the value of the patched items, only the patched methods show up as MagicMock

    >>> boto3.client
        <MagicMock name='client...>
    >>> ASOUsecaseTools.get_by_name
        <MagicMock name='get_by_name...>
    >>> asodates2datetime
        <function asodates2datetime...>
    >>> date
        <class 'datetime.date'>

The thing that confuses me is that I am patching along with how the docs say to patch: https://docs.python.org/3/library/unittest.mock-examples.html#partial-mocking

Also the fact that patched methods work but classes and functions don't indicates that the import structure is not a problem because the imported methods would be overwritten in the same way as the imported classes. It also indicates that the import paths are not incorrect; as the only difference between the patches is the type of object they are patching.

My current workaround is using the freeze package to freeze the date, but I prefer using builtin packages if possible.

CPython versions tested on:

3.9

Operating systems tested on:

macOS

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par le reproducteur unittest.mock fourni dans l’issue et comparez ses cibles de patch avec la documentation liée sur le partial mocking. Vérifiez le comportement sur CPython 3.9, puis déterminez si la différence observée est un bug reproductible de l’interpréteur ou une incompréhension concernant les imports ou le patching ; un test concret qui échoue et le comportement attendu définiraient ce qui constitue la fin du travail.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
testing-qa
Type d'issue
Bug
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
À clarifier
Accessibilité débutants
25/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.