python / python/mypy

Fully-fledged support for mocked objects

Aperta
#9,776 8 commenti 15 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

feature
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Feature

I'd like to propose that fully-fledged support for mocked objects be added so that type checks work with spec'd mocks.

import mock
import typing


class Foo:
    def bar(self, a: int) -> str:
        return str(a)


# I want to pass a spec'd mock here (mock.create_autospec(spec=Foo)).
def test_something(foo: Foo):
    # I'd like to find a way for this to be accepted by mypy.
    # error: "Callable[[int], str]" has no attribute "return_value"
    foo.bar.return_value = "42"


# This can be resolved arduously by writing a custom protocol for each mock.
class BarMockProtocol(typing.Protocol):
    return_value: str

    def __call__(self, a: int) -> str:
        pass

    # def assert_called():
    #     ...
    # And so on...


class FooMockProtocol(typing.Protocol):
    bar: BarMockProtocol


def test_something_else(foo: FooMockProtocol):
    # Error as expected.
    # error: Incompatible types in assignment (expression has type "int", variable has type "str")
    foo.bar.return_value = 42

    # No error as expected.
    foo.bar.return_value = "42"


# This is what I'd suggest
def test_something_else_yet(foo: mock.Mock[Foo]):
    # Error
    foo.bar.return_value = 42
    # No error
    foo.bar.return_value = "42"


# Usage sample
foo_mock = mock.create_autospec(spec=Foo)
test_something_else_yet(foo_mock)

Pitch

Currently, it's difficult to fully utilise mypy with mocks. I can see the following options.

  1. Use typing.Any to disable type checks.
  2. Use the type of the mocked class and live/deal with errors when using mock-specific attributes and methods (e.g. return_value, assert_*).
  3. Write a custom protocol for every mocked class as demonstrated above.

In other words, it's a choice between boilerplate and limitations. Please do let me know if I missed anything.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Non sono indicati file di implementazione né test. Inizia riproducendo in mypy gli esempi di Foo, create_autospec e Mock dell’issue, quindi esamina come vengono tipizzati gli oggetti mockati e gli attributi chiamabili. Il lavoro è completato quando i mock con spec supportano assegnazioni a return_value verificate dal tipo senza protocolli personalizzati, mantenendo al contempo gli errori per i valori incompatibili.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
devtools, testing-qa
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Da chiarire
Idoneità per principianti
25/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.