Python unittes中keystoneclient的模拟和修补

2024-04-25 12:15:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为如下所示的类编写unittest。我试图断言是否使用补丁keystoneclient正确地调用了日志记录。该类如下所示。问题是,我无法通过for语句,也无法到达记录器。警告或者记录器信息即使是在修补了CredentialManager之后。我对整个unittest和Mock都是新手,所以我可能对某些东西理解不清楚。在

from keystoneclient.v3.client import Client
from keystoneclient.v3.credentials import CredentialManager
import logging

LOGGER = logging.getLogger(__name__)

class MyClass(object):

    def __init__(self):
    ...

    def myfunc(self):

        new_credentials = {}
        client = Client(
            username=self.username,
            password=self.password,
            auth_url=self.auth_url,
            user_domain_name=self.user_domain_name,
            domain_name=self.domain_name
        )

        abc = CredentialManager(client)

        for credential in abc.list():

            defg = str(credential.type)
            (access, secret) = _anotherfunc(credential.blob)

            if not defg:
                LOGGER.warning('no abc')

            if defg in new_credentials:
                LOGGER.info('Ignoring duplate')

            new_credentials[defg] = (access, secret)

我的单元测试看起来像这样

^{pr2}$

我得到的错误看起来像这样。在

    for credential in abc.list():
AttributeError: 'tuple' object has no attribute 'list'

因此,即使在用autospect修补CredentialManager之后,我还是会出错abc列表(). 我需要达到可以测试LOGGER的程度,但是这个补丁似乎不适用于list()。我应该如何消除这个错误,并且能够通过for语句,以便在日志中声明?在


Tags: nameimportselfclientnewfordomainlogger
1条回答
网友
1楼 · 发布于 2024-04-25 12:15:47

这个答案要包括多少细节:

  1. 修补程序顺序:@patchdecorator作为堆栈应用,这意味着第一个decorator->最后一个mock参数
  2. 如果您希望CredentialManager().list()返回包含空type的内容,您应该使用mock_cm来执行此操作
  3. 如果您想测试某个东西,您应该调用obj.myfunc()来测试:)

代码:

导入单元测试 从mock import补丁,mock 导入MyClass

@patch('MyClass.Client', autospec=True)
@patch('MyClass.CredentialManager', autospec=True)
class TestMyClass(unittest.TestCase):
    #Use decorator for test case too... is simpler and neat
    @patch("MyClass.LOGGER", autospec=True)
    def test_logger_warning(self, mock_logger, mock_cm, mock_client):
        #pay attention to the mock argument order (first local and the the stack of patches
        # Extract the mock that will represent you abc
        mock_abc = mock_cm.return_value
        # Build a mock for credential with desidered empty type
        mock_credential = Mock(type="")
        # Intrument list() method to return your credential
        mock_abc.list.return_value = [mock_credential]
        obj = MyClass.MyClass()
        # Call the method
        obj.myfunc()
        # Check your logger
        mock_logger.warning.assert_called_with('no abc')

在所有补丁中使用autospec=True是一个很好的做法。在

不管怎样,我想鼓励您将日志记录部分提取到一个方法中,并用一些假凭证来测试它:更简单、更好的设计:类似

^{pr2}$

测试更简单,看起来更好。在

相关问题 更多 >