如何为python单元测试提供模拟类方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38579535/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 21:08:41  来源:igfitidea点击:

How to supply a mock class method for python unit test?

pythonunit-testingmocking

提问by Vineel

Let's say I have a class like this.

假设我有一堂这样的课。

   class SomeProductionProcess(CustomCachedSingleTon):

       def loaddata():
           """
           Uses an iterator over a large file in Production for the Data pipeline.
           """

           pass

Now at test time I want to change the logic inside the loaddata()method. It would be a simple custom logic that doesn't process large data.

现在在测试时我想更改loaddata()方法内部的逻辑。这将是一个不处理大数据的简单自定义逻辑。

How do we supply custom implementation of loaddata()at testtime using Python Mock UnitTest framework?

我们如何loaddata()在测试时使用 Python Mock UnitTest 框架提供自定义实现?

回答by Brendan Abel

Here is a simple way to do it using mock

这是使用模拟的简单方法

import mock


def new_loaddata(cls, *args, **kwargs):
    # Your custom testing override
    return 1


def test_SomeProductionProcess():
    with mock.patch.object(SomeProductionProcess, 'loaddata', new=new_loaddata):
        obj = SomeProductionProcess()
        obj.loaddata()  # This will call your mock method

I'd recommend using pytestinstead of the unittestmodule if you're able. It makes your test code a lot cleaner and reduces a lot of the boilerplate you get with unittest.TestCase-style tests.

如果可以pytest,我建议使用而不是unittest模块。它使您的测试代码更加清晰,并减少了您通过unittest.TestCase-style 测试获得的大量样板。

回答by Mattew Whitt

To easily mock out a class method with a structured return_value, can use unittest.mock.Mock.

要轻松模拟具有结构化 return_value 的类方法,可以使用unittest.mock.Mock.

from unittest.mock import Mock

mockObject = SomeProductionProcess
mockObject.loaddata = Mock(return_value=True)

EDIT:

编辑:

Since you want to mock out the method with a custom implementation, you could just create a custom mock method object and swap out the original method at testing runtime.

由于您想使用自定义实现来模拟方法,因此您可以创建自定义模拟方法对象并在测试运行时换出原始方法。

def custom_method(*args, **kwargs):
    # do custom implementation

SomeProductionProcess.loaddata = custom_method

回答by willnx

Lets say you have a module named awesome.pyand in it, you had:

假设您有一个名为awesome.py的模块,其中包含:

import time

class SomeProductionProcess(CustomCachedSingleTon):

    def loaddata(self):
        time.sleep(30) # simulating a long running process
        return 2

Then your unittest where you mock loaddatacould look like this:

然后你模拟的单元测试loaddata可能看起来像这样:

import unittest

import awesome # your application module


class TestSomeProductionProcess(unittest.TestCase):
    """Example of direct monkey patching"""

    def test_loaddata(self):
        some_prod_proc = awesome.SomeProductionProcess()
        some_prod_proc.loaddata = lambda x: 2 # will return 2 every time called
        output = some_prod_proc.loaddata()
        expected = 2

        self.assertEqual(output, expected)

Or it could look like this:

或者它看起来像这样:

import unittest
from mock import patch

import awesome # your application module

class TestSomeProductionProcess(unittest.TestCase):
    """Example of using the mock.patch function"""

    @patch.object(awesome.SomeProductionProcess, 'loaddata')
    def test_loaddata(self, fake_loaddata):
        fake_loaddata.return_value = 2
        some_prod_proc = awesome.SomeProductionProcess()

        output = some_prod_proc.loaddata()
        expected = 2

        self.assertEqual(output, expected)

Now when you run your test, loaddatawont take 30 seconds for those test cases.

现在,当您运行测试时,loaddata这些测试用例不会花费 30 秒。