可测试的单例装饰器
singleton-decorator的Python项目详细描述
单例装饰器
可测试的单例装饰器允许轻松创建单例对象 只需在类定义中添加一个decorator,而且还允许轻松地编写 这些类的单元测试。
一个问题
如果使用基于decorator函数的简单单例模式 用这样的内部包装函数包装类:
def singleton(cls): instances = {} def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper
它可以很好地与您的类一起工作,但是它使得不可能直接访问 到没有decorator的类对象。所以不能使用 单元测试中的类名:
@singleton class YourClass: def method(self): ... YourClass.method(...)
此代码无法工作,因为YouClass实际上包含一个包装函数 但不是你的类对象。如果您的 测试需要对象的单独实例,因此单例模式可以 打破不同测试的隔离。
溶液
singleton decorator提供了一个简单的解决方案来避免这两种情况 问题。它为每个修饰类使用单独的包装器对象,并保存 __wrapped__属性中的类,以便您可以访问修饰的类 直接在你的单元测试中。
安装
要安装singleton decorator只需在命令行中键入:
$ pip install singleton-decorator
用法
首先导入singleton decorator:
from singleton_decorator import singleton
然后用这个decorator装饰您的类:
@singleton class YourClass: ...
就这些。现在,您可以创建或获取类的现有实例。 将其称为简单的类对象:
obj = YourClass() # creates a new instance obj2 = YourClass() # returns the same instance obj3 = YourClass() # returns the same instance ...
您还可以将args和kwargs传递到类的构造函数中:
obj = YourClass(1, "foo", bar="baz")
注意
因为singleton模式只允许从 类__init__方法将用args和 第一次打电话时夸尔格斯就过去了。所有未来电话的争论 完全忽视,不会影响现有的实例。
单元测试
在您的单元测试中单独运行修饰类的方法 不实例化对象(避免运行构造函数代码)。 使用包装器对象的__wrapped__属性:
# your_module.py @singleton class YourClass: def your_method(self): ...
# tests.py class TestYourClass(TestCase): def test_your_method(self): obj = mock.MagicMock() YourClass.__wrapped__.your_method(obj) ...
此测试仅使用模拟对象运行your_method的代码 作为self参数,因此测试将在完全隔离的情况下运行 不会依赖于其他代码片段,包括构造函数 方法。