summaryrefslogtreecommitdiffstats
path: root/tests/test_ext_autodoc_mock.py
blob: 3b90693efc2daa5656dced4a8a0ef775ec465505 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""Test the autodoc extension."""

from __future__ import annotations

import abc
import sys
from importlib import import_module
from typing import TypeVar

import pytest

from sphinx.ext.autodoc.mock import _MockModule, _MockObject, ismock, mock, undecorate


def test_MockModule():
    mock = _MockModule('mocked_module')
    assert isinstance(mock.some_attr, _MockObject)
    assert isinstance(mock.some_method, _MockObject)
    assert isinstance(mock.attr1.attr2, _MockObject)
    assert isinstance(mock.attr1.attr2.meth(), _MockObject)

    assert repr(mock.some_attr) == 'mocked_module.some_attr'
    assert repr(mock.some_method) == 'mocked_module.some_method'
    assert repr(mock.attr1.attr2) == 'mocked_module.attr1.attr2'
    assert repr(mock.attr1.attr2.meth) == 'mocked_module.attr1.attr2.meth'

    assert repr(mock) == 'mocked_module'


def test_MockObject():
    mock = _MockObject()
    assert isinstance(mock.some_attr, _MockObject)
    assert isinstance(mock.some_method, _MockObject)
    assert isinstance(mock.attr1.attr2, _MockObject)
    assert isinstance(mock.attr1.attr2.meth(), _MockObject)

    # subclassing
    class SubClass(mock.SomeClass):
        """docstring of SubClass"""

        def method(self):
            return "string"

    obj = SubClass()
    assert SubClass.__doc__ == "docstring of SubClass"
    assert isinstance(obj, SubClass)
    assert obj.method() == "string"
    assert isinstance(obj.other_method(), SubClass)

    # parametrized type
    T = TypeVar('T')

    class SubClass2(mock.SomeClass[T]):
        """docstring of SubClass"""

    obj2 = SubClass2()
    assert SubClass2.__doc__ == "docstring of SubClass"
    assert isinstance(obj2, SubClass2)


def test_mock():
    modname = 'sphinx.unknown'
    submodule = modname + '.submodule'
    assert modname not in sys.modules
    with pytest.raises(ImportError):
        import_module(modname)

    with mock([modname]):
        import_module(modname)
        assert modname in sys.modules
        assert isinstance(sys.modules[modname], _MockModule)

        # submodules are also mocked
        import_module(submodule)
        assert submodule in sys.modules
        assert isinstance(sys.modules[submodule], _MockModule)

    assert modname not in sys.modules
    with pytest.raises(ImportError):
        import_module(modname)


def test_mock_does_not_follow_upper_modules():
    with mock(['sphinx.unknown.module']):  # NoQA: SIM117
        with pytest.raises(ImportError):
            import_module('sphinx.unknown')


def test_abc_MockObject():
    mock = _MockObject()

    class Base:
        @abc.abstractmethod
        def __init__(self):
            pass

    class Derived(Base, mock.SubClass):
        pass

    obj = Derived()
    assert isinstance(obj, Base)
    assert isinstance(obj, _MockObject)
    assert isinstance(obj.some_method(), Derived)


def test_mock_decorator():
    mock = _MockObject()

    @mock.function_deco
    def func():
        pass

    class Foo:
        @mock.method_deco
        def meth(self):
            pass

        @classmethod
        @mock.method_deco
        def class_meth(cls):
            pass

    @mock.class_deco
    class Bar:
        pass

    @mock.funcion_deco(Foo)
    class Baz:
        pass

    assert undecorate(func).__name__ == "func"
    assert undecorate(Foo.meth).__name__ == "meth"
    assert undecorate(Foo.class_meth).__name__ == "class_meth"
    assert undecorate(Bar).__name__ == "Bar"
    assert undecorate(Baz).__name__ == "Baz"


def test_ismock():
    with mock(['sphinx.unknown']):
        mod1 = import_module('sphinx.unknown')
        mod2 = import_module('sphinx.application')

        class Inherited(mod1.Class):
            pass

        assert ismock(mod1) is True
        assert ismock(mod1.Class) is True
        assert ismock(mod1.submod.Class) is True
        assert ismock(Inherited) is False

        assert ismock(mod2) is False
        assert ismock(mod2.Sphinx) is False