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

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

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

问题

  1. 所以假设允许
  2. ```python
  3. services/foo.py
  4. from apps.bar import BarClass
  5. static_foos = BarClass().get_statics()
  6. class FooService():
  7. ....

和测试代码如下:

  1. tests/test_foo.py
  2. from services.foo import FooService
  3. def test_foo_something():
  4. assert FooService.something() == True

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

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

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

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

  1. <details>
  2. <summary>英文:</summary>
  3. So assume the allowing :

services/foo.py

from apps.bar import BarClass

static_foos = BarClass().get_statics()

class FooService() :
....

  1. and test code looking like :

tests/test_foo.py

from services.foo import FooService

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

  1. 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.
  2. 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.
  3. 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).
  4. Is there any possible solution in this case?
  5. </details>
  6. # 答案1
  7. **得分**: 2
  8. ```python
  9. 您可以在测试函数内部导入`services.foo`模块,*在*您对`requests.get`进行monkey-patch之后:
  10. import requests
  11. # 在这里定义您的MockResponse类
  12. def test_foo_something(monkeypatch):
  13. def mock_get(*args, **kwargs):
  14. return MockResponse()
  15. monkeypatch.setattr(requests, "get", mock_get)
  16. from services.foo import FooService
  17. assert FooService.something() == True
英文:

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

  1. import requests
  2. # define your MockResponse class here
  3. def test_foo_something(monkeypatch):
  4. def mock_get(*args, **kwargs):
  5. return MockResponse()
  6. monkeypatch.setattr(requests, &quot;get&quot;, mock_get)
  7. from services.foo import FooService
  8. assert FooService.something() == True

答案2

得分: 2

  1. 您可以在导入`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

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

from apps.bar import BarClass

static_foos = None

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

class FooService():
...

  1. <details>
  2. <summary>英文:</summary>
  3. 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

  1. 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():
...

  1. </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:

确定