【问题标题】:mocking API calls in unit testing在单元测试中模拟 API 调用
【发布时间】:2017-03-15 19:31:54
【问题描述】:

我对 Python 还很陌生,很难弄清楚如何在单元测试中模拟补丁 API 调用。 仅供参考,我正在使用 Python 2.7 并使用 nosetest 来满足我的单元测试需求。

我有以下模块(myRedis.py),我想对其进行单元测试:

import logging
import redis

redispool = None

class myRedis(object):

def __init__(self, redisHost, redisPort, redisDBNum):
    if not redisPort.isdigit():
        raise TypeError('Exception: Expected int for redisPort')

    if not redisDBNum.isdigit():
        raise TypeError('Exception: Expected int for redisDBNum')

    self._redis_instance = None

    self._redishost = redisHost
    self._redisport = redisPort
    self._redisdb = redisDBNum

    global redispool
    redispool = redis.ConnectionPool(host=self._redishost,
                                          port=self._redisport,
                                          db=self._redisdb)

    def redis_connect(self):
         LOGGER.info('Connecting Redis client to %s:%s:%s', self._redishost,
         self._redisport, self._redisdb)
         self._redis_instance = redis.StrictRedis(connection_pool=redispool)

    def write_redis(self, key, value):
         retval = self._redis_instance.set(key, value)
         LOGGER.info('Writing data to redis (%s, %s). Retval=%s', key, value, retval)
         return retval

    def read_redis(self, key):
         retval = self._redis_instance.get(key) 
         LOGGER.info('Reading data from redis: key=%s. Retval=%s', key, retval)
         return retval

就单元测试而言,到目前为止,我有以下内容。

from nose.tools import *
import mock
from myRedis import myRedis

def setup():
    pass
def teardown():
    pass

@mock.patch('redis.StrictRedis')
def test_mock_redis_StrictRedis(mock_conn_pool):
    mock_conn_pool.return_value = True
    assert(True)

def test_myRedis():

    assert_raises(TypeError, myRedis, 
              'test', '1234', 'a11')

    assert_raises(TypeError, myRedis, 
              'test', 'a1234', '11')

    myRedisObj = myRedis('localhost', '8888', '11')
    assert_equal(myRedisObj._redishost, 'localhost')
    assert_equal(myRedisObj._redisport, '8888')
    assert_equal(myRedisObj._redisdb, '11')

    myRedisObj.redis_connect()
    #oclRedis.read_redis('test')
    #oclRedis.write_redis('test', 'test')

我可以毫无问题地修补 redis.StrictRedis() 调用。但是如何修补 redis 的 get() 和 set() 调用,因为它们是在对象上调用的(myRedis.py 中的 _redis_instance)。我尝试了几个不同版本的@mock.patch.object,但这对我不起作用。寻求一些指导。

提前致谢。

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    您应该修补的不是来自对象的实际调用,而是这些调用正在调用的对象本身。

    在您的代码中,它会类似于以下内容:

    from nose.tools import *
    import mock
    import unittest
    from red import myRedis
    
    def setup():
        pass
    def teardown():
        pass
    
    @mock.patch('redis.StrictRedis')
    def test_mock_redis_StrictRedis(mock_conn_pool):
        mock_conn_pool.return_value = True
        assert(True)
    
    def test_myRedis_wrong_args():
        assert_raises(TypeError, myRedis,
                  'test', '1234', 'a11')
        assert_raises(TypeError, myRedis,
                  'test', 'a1234', '11')
    
    def test_myRedis_ok():
        myRedisObj = myRedis('localhost', '8888', '11')
        assert_equal(myRedisObj._redishost, 'localhost')
        assert_equal(myRedisObj._redisport, '8888')
        assert_equal(myRedisObj._redisdb, '11')
    
    
    @mock.patch('redis.StrictRedis.set')
    def test_myRedis_write(mock_strict_redis_set):
        mock_strict_redis_set.return_value = {}
        myRedisObj = myRedis('localhost', '8888', '11')
        redis_connect = myRedisObj.redis_connect()
        connect = myRedisObj.write_redis('1', '2')
        assert connect == {}
    

    如您所见,我修改了您的测试以一次测试一件事。这是您通常想要做的事情,以避免副作用并保证测试隔离。

    考虑查看文档:https://docs.python.org/dev/library/unittest.mock.html

    最后缩进是 Python 的关键,考虑在你的代码 sn-ps 中正确缩进

    【讨论】:

      猜你喜欢
      • 2021-11-05
      • 2015-04-03
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      相关资源
      最近更新 更多