Python Mock 第三方模块

4 投票
1 回答
8051 浏览
提问于 2025-04-18 02:59

我正在尝试测试一些处理推文的类。我使用的是sixohsix的Twitter库来处理Twitter的API。
我有一个类,它充当Twitter类的外观(也就是一个简化接口),我的想法是模拟实际的sixohsix类,以便模拟推文的到来,方法是随机生成新的推文或者从数据库中获取推文。

我的外观类大致是这样的:

from twitter import TwitterStream


class TwitterFacade(object):
    def __init__(self, dev='soom'):
        self._auth = OAuth(dev_keys["ACCESS_TOKEN"], dev_keys["ACCESS_SECRET"],   dev_keys["CONSUMER_KEY"], dev_keys["CONSUMER_SECRET"])

    def tweets(self, callback=None, users=[], terms=[], locations=[], count=5):
        t = TwitterStream(auth=self._auth)

        args = {}
        if users:     args['follow']    = ",".join(users)
        if terms:     args['track']     = ",".join(terms)
        if locations: args['locations'] = ",".join(str(l) for l in locations)

        # this controls the general loop, it re-enters if there was an exception,
        # otherwise the for loop should take care of looping trough the tweets
        cant = count
        while cant > 0:
            try:
                iterator = t.statuses.filter(**args)
                for twit in iterator:
                    if twit.get('text'):
                        callback(twit)
                        cant -= 1
                        if cant == 0:
                            iterator.close()
                            break
            except Exception as e:
                print e
                #some error handling code

那么,如果在单元测试中我想测试某个模块,它会对推文进行一些操作,我该如何模拟TwitterStream类呢?
我尝试使用Mock来实现:

from mock import patch
from twitter_facade import TwitterFacade


class TwitterStreamProxy(object):
    def __init__(self):
        pass
        #some code for dealing with statuses.filter(..)


@patch('twitter.TwitterStream', TwitterStreamProxy())
def test_filter_on_tweets():
    facade = TwitterFacade()
    facade.tweets(somemethod, [], ['term1', 'term2'], [], count=50)

def somemethod(tweet):
    #some logic in here

但这并没有成功,Twitter的API仍然被调用。我本以为因为我没有在模拟类中添加任何代码,所以会出现错误或其他问题,但实际上却调用了sixohsix的Twitter类。

1 个回答

12

你需要对本地对象进行修补;你的模块里有一个指向TwitterStream对象的引用,修补这个对象:

@patch('yourmodule.TwitterStream', TwitterStreamProxy())

可以查看这个模拟的在哪里修补的文档。

撰写回答