在Pytest中,有一种方法可以在收集测试时“模拟”或阻止某些操作吗?

huangapple go评论72阅读模式
英文:

In Pytest, Is there a way to "mock" or prevent something from happening while collecting test?

问题

所以假设允许

```python
 services/foo.py

from apps.bar import BarClass

static_foos = BarClass().get_statics()

class FooService():
     ....

和测试代码如下:

 tests/test_foo.py

from services.foo import FooService

def test_foo_something():
    assert FooService.something() == True

在这里,当pytest收集测试时,它似乎在我的任何尝试在conftest.py中模拟或阻止访问之前执行了BarClass.get_statics()

更具体地说,假设get_statics() 在其中有一些requests.get,pytest中阻止网络的典型方法,即模拟socket.socket,并不起作用。

据我所知,在测试被收集之前执行某些操作的唯一方法是在conftest.py中使用pytest_configure,但是据我所知,它不允许我进行模拟,这让我现在完全失去了希望(而且由于各种原因,我实际上也无法真正更改test_something的内容)。

在这种情况下有可能的解决方案吗?


<details>
<summary>英文:</summary>

So assume the allowing :


services/foo.py

from apps.bar import BarClass

static_foos = BarClass().get_statics()

class FooService() :
....

and test code looking like :

tests/test_foo.py

from services.foo import FooService

def test_foo_something() :
assert FooService.something() == True




So here, when the pytest collects the test, it seems like it executes `BarClass.get_statics()` even before any of my attempts to mock or block access in `conftest.py` to kick in.

To be more specific, assuming `get_statics()` has some `requests.get` in it, a typical way of blocking network in pytest, which is mocking `socket.socket`, is not working.


From my knowledge, the only way to do something before tests get collected is to use `pytest_configure` in `conftest.py`, but also AFAIK it doesn&#39;t allow me to mock meaning that I&#39;m just completely losing hope right now (Also it&#39;s not like I can really change the content of `test_something` for various reasons).

Is there any possible solution in this case?
 

</details>


# 答案1
**得分**: 2

```python
您可以在测试函数内部导入`services.foo`模块,*在*您对`requests.get`进行monkey-patch之后:

    import requests

    # 在这里定义您的MockResponse类

    def test_foo_something(monkeypatch):
        def mock_get(*args, **kwargs):
            return MockResponse()

        monkeypatch.setattr(requests, "get", mock_get)
        from services.foo import FooService

        assert FooService.something() == True
英文:

You can import the services.foo module within the test function instead, after you monkey-patch requests.get:

import requests

# define your MockResponse class here

def test_foo_something(monkeypatch):
    def mock_get(*args, **kwargs):
        return MockResponse()

    monkeypatch.setattr(requests, &quot;get&quot;, mock_get)
    from services.foo import FooService

    assert FooService.something() == True

答案2

得分: 2

您可以在导入`FooService`之前`apps.bar`中导入`BarClass`并模拟`get_statics`。例如

from apps.bar import BarClass

def do_nothing(*args, **kwargs):
pass

BarClass.get_statics = do_nothing

from services.foo import FooService

def test_foo_something():
assert FooService.something() == True

但是我认为最好在`services.foo`中添加一些初始化函数,并在需要时调用它。类似于:

from apps.bar import BarClass

static_foos = None

def init():
static_foos = BarClass().get_statics()

class FooService():
...


<details>
<summary>英文:</summary>

You can import `BarClass` from `apps.bar` right before importing `FooService` and mock the `get_statics`. For example:

from apps.bar import BarClass

def do_nothing(*args, **kwargs):
pass

BarClass.get_statics = do_nothing

from services.foo import FooService

def test_foo_something() :
assert FooService.something() == True

However I think it would be better to add some initializing function to `services.foo` and call it when its needed. Something like:

from apps.bar import BarClass

static_foos = None

def init():
static_foos = BarClass().get_statics()

class FooService():
...


</details>



huangapple
  • 本文由 发表于 2023年3月7日 15:17:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75658965.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定