如何将Mock.ANY与assert_Called_with一起使用

Fra*_* T. 6 python unit-testing mocking

我被封锁了

我正在用鼻子测试和模拟创建测试。我很难,很难理解如何正确执行此操作。在这里,我想确保使用正确的参数调用subprocess.check_output。我收到此错误消息:

AssertionError: Expected call: check_output(['dscl', '/Search', 'read', '/Users/testuser', 'AuthenticationAuthority'], <ANY>)
Actual call: check_output(['dscl', '/Search', 'read', '/Users/testuser', 'AuthenticationAuthority'], stderr=-2)
Run Code Online (Sandbox Code Playgroud)

Mock.ANY不是通配符吗?我误会了吗?

我不懂事,请告诉我我是否愚蠢。

KerbMinder2.py:

def get_current_username():
"""Returns the user associated with the LaunchAgent running KerbMinder.py"""
    return getpass.getuser()

@staticmethod
def get_principal_from_ad():
    """Returns the principal of the current user when computer is bound"""

    import re

    user_path = '/Users/' + get_current_username()

    try:
        output = subprocess.check_output(['dscl',
                                          '/Search',
                                          'read',
                                          user_path,
                                          'AuthenticationAuthority'],
                                         stderr=subprocess.STDOUT)
        match = re.search(r'[a-zA-Z0-9+_\-\.]+@[^;]+\.[A-Z]{2,}', output, re.IGNORECASE)
        match = match.group()

    except subprocess.CalledProcessError as error:
        log_print("Can't find Principal from AD: " + str(error))

    else:
        log_print('Kerberos Principal is ' + match)
        return match
Run Code Online (Sandbox Code Playgroud)

test_KerbMinder2.py:

@patch('KerbMinder2.get_current_username')
def test_ad_bound_notenabled(self, mock_get_current_username):
    #https://github.com/nens/nensbuild/blob/master/nensbuild/tests.py
    mock_get_current_username.return_value = "testuser"

    _return_value = 'AuthenticationAuthority:  ;ShadowHash;HASHLIST:' \
                    '<SMB-NT,CRAM-MD5,RECOVERABLE,SALTED-SHA512-PBKDF2>  ' \
                    ';LocalCachedUser;/Active Directory/TEST/test.com:testuser' \
                    ':9A1F2D0C-B782-488A-80BA-CAC95AB6CAE9  ;Kerberosv5;;testuser@TEST.COM;' \
                    'TEST.COM; AuthenticationAuthority: ;Kerberosv5;;testuser@TEST.COM;TEST.COM; ' \
                    ';NetLogon;testuser;TEST'
    with patch('subprocess.check_output', return_value = _return_value) as check_output:
        nose.tools.eq_(Principal.get_principal_from_ad(), "testuser@TEST.COM")
    check_output.assert_called_with(['dscl',
                                      '/Search',
                                      'read',
                                      '/Users/testuser',
                                      'AuthenticationAuthority'],
                                      ANY)
Run Code Online (Sandbox Code Playgroud)

结果

test_ad_bound_notenabled (test_KerbMinder2.TestPrincipal) ... 
FAIL


Failure
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 331, in run
    testMethod()
  File "/Users/francois/venv-KerbMinder2/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
    return func(*args, **keywargs)
  File "/Users/francois/Git/KerbMinder2/Library/Application Support/crankd/test_KerbMinder2.py", line 61, in test_ad_bound_notenabled
    ANY)
  File "/Users/francois/venv-KerbMinder2/lib/python2.7/site-packages/mock/mock.py", line 937, in assert_called_with
    six.raise_from(AssertionError(_error_message(cause)), cause)
  File "/Users/francois/venv-KerbMinder2/lib/python2.7/site-packages/six.py", line 718, in raise_from
    raise value
AssertionError: Expected call: check_output(['dscl', '/Search', 'read', '/Users/testuser', 'AuthenticationAuthority'], <ANY>)
Actual call: check_output(['dscl', '/Search', 'read', '/Users/testuser', 'AuthenticationAuthority'], stderr=-2)
-------------------- >> begin captured stdout << ---------------------
Kerberos Principal is testuser@TEST.COM

--------------------- >> end captured stdout << ----------------------
Run Code Online (Sandbox Code Playgroud)

Eli*_*les 7

AFAIK,您必须指定关键字参数名称才能使用通配符 ANY。

另一种选择是直接使用mock_calls以下方法在调用列表上直接断言:

with patch('subprocess.check_output') as check_output:
    ... code to test here ...
    func_name, args, kwargs = check_output.mock_calls[0]

    assert func_name == 'check_output'
    assert args == [list of positional args]
    assert kwargs == {dict of keyword args} # in your case, you'd leave this out
Run Code Online (Sandbox Code Playgroud)