如何模拟不同模块的pika连接?

时间:2019-04-15 23:58:40

标签: python mocking rabbitmq python-unittest pika

我有一个导入以下模块的类:

$appCmdCommand2 = "appcmd.exe set config -section:system.applicationHost/sites /+`"[name='Default Web Site'].[path='/'].[path='/MyWebsite/dev',physicalPath='{0}']`" /commit:apphost" -f $folderName

Invoke-Command -ComputerName ComputerAA -ScriptBlock {$appCmdCommand2}

我的class.py:

import pika
import pickle
from apscheduler.schedulers.background import BackgroundScheduler
import time
import logging
class RabbitMQ():
    def __init__(self):
        self.connection = pika.BlockingConnection(pika.ConnectionParameters(host="localhost"))
        self.channel = self.connection.channel()
        self.sched = BackgroundScheduler()
        self.sched.add_job(self.keep_connection_alive, id='clean_old_data', trigger='cron', hour = '*', minute='*', second='*/50')
        self.sched.start()
    def publish_message(self, message , path="path"):
        message["path"] = path
        logging.info(message)
        message = pickle.dumps(message)
        self.channel.basic_publish(exchange="", routing_key="server", body=message)
    def keep_connection_alive(self):
        self.connection.process_data_events()
rabbitMQ = RabbitMQ()
def publish_message(message , path="path"):
    rabbitMQ.publish_message(message, path=path)

为MyClass生成单元测试时,我无法模拟此部分代码的连接。并保持抛出异常。而且根本不起作用

import RabbitMQ as rq
class MyClass():
...

我尝试了几种方法来模拟此连接,但这些方法似乎都不起作用。我想知道如何做才能支持这种测试?模拟整个RabbitMQ模块?或者也许只模拟连接

1 个答案:

答案 0 :(得分:0)

就像上面的评论者一样,问题是您对RabbitMQ的全局创建。

我的下意识的反应是说“只要摆脱它,您的模块级publish_message”就可以了。如果可以做到,请寻求该解决方案。您的publish_message类上有一个RabbitMQ,它接受​​相同的参数。这样,任何调用者都将创建您的RabbitMQ类的实例。

如果出于某种原因您不愿意或不愿意这样做,则应仅在模块级移动该对象实例化的实例化publish_message像这样:

def publish_message(message , path="path"):
    rabbitMQ = RabbitMQ()
    rabbitMQ.publish_message(message, path=path)

这将在每次调用时创建一个新连接。也许还可以...但事实并非如此。因此,为避免创建重复的连接,您想引入类似单例模​​式的内容:

class RabbitMQ():
    __instance = None

    ...

    @classmethod
    def get_instance(cls):
        if cls.__instance is None:
            cls.__instance = RabbitMQ()
        return cls.__instance

def publish_message(message , path="path"):
    RabbitMQ.get_instance().publish_message(message, path=path)

但是理想情况下,您希望完全避免使用单例模式。无论哪个调用者应存储您的RabbitMQ对象的单个实例,然后直接在其上调用publish_message

因此TLDR /理想解决方案IMO:只需摆脱最后3行。调用者应创建一个RabbitMQ对象。

编辑:哦,为什么正在发生-导入该模块时,正在对此进行评估:rabbitMQ = RabbitMQ()。评估之后,您正在尝试模拟它,但是无法连接。