我有一个数据访问类,它从数据库中获取数据。它是作为混合实现的,即 ReferenceData 我想将此类与 MockReferenceData 类交换,因此在单元测试中我不必访问数据库。但不起作用。
*注意:我无法使用依赖注入(inject)。由于团队不想使用它,因为考虑到这将是非常大的代码更改。所以我希望在运行时替换 mixin。
class MockReferenceData(object):
def dbName(self):
return 'mock'
def totalNumberOfSeats(self):
return '10'
class ReferenceData(object):
def dbName(self):
return 'real DB'
def totalNumberOfSeats(self):
return 'Fetch from DB'
class Car(ReferenceData):
def showNumberOfSeats(self):
print self.totalNumberOfSeats()
class Train(ReferenceData):
def showNumberOfSeats(self):
print self.totalNumberOfSeats()
c = Car()
c.showNumberOfSeats()
t = Train()
t.showNumberOfSeats()
def extend_instance(obj, cls):
"""Apply mixins to a class instance after creation"""
base_cls = obj.__class__
base_cls_name = obj.__class__.__name__
obj.__class__ = type(base_cls_name, (base_cls, cls),{})
extend_instance(c, MockReferenceData)
c.showNumberOfSeats() // output now should be 10
输出是:
Fetch from DB
Fetch from DB
Fetch from DB
我希望因为我使用了 extend_instance 方法来指向新的模拟类输出将是:
Fetch from DB
Fetch from DB
10
最佳答案
如果你看MRO类(class)Car
你可以看到:
>>> Car.__mro__
(<class '__main__.Car'>, <class '__main__.ReferenceData'>, <type 'object'>)
因此首先在 Car
上查找方法,然后点击ReferenceData
最后是object
.
将其与新类的 MRO 进行比较(为了清楚起见,我使用 NewCar
作为名称):
>>> type('NewCar', (Car, MockReferenceData), {}).__mro__
(<class '__main__.NewCar'>, <class '__main__.Car'>, <class '__main__.ReferenceData'>, <class '__main__.MockReferenceData'>, <type 'object'>)
这包含 Car
的 MRO类(class)。这里的方法仍然首先在 Car
上查找然后ReferenceData
,如totalNumberOfSeats
发现于ReferenceData
MockReferenceData
的实现未使用。
您可以做的是将模拟类插入 MRO 中的 Car
之前类:
>>> type('NewCar', (MockReferenceData, Car), {}).__mro__
(<class '__main__.NewCar'>, <class '__main__.MockReferenceData'>, <class '__main__.Car'>, <class '__main__.ReferenceData'>, <type 'object'>)
现在方法将首先在 MockReferenceData
中查找类,如果它们不存在,则回退到以前的版本。所以这个extend_instance
方法应该适用于这个简单的情况:
def extend_instance(obj, cls):
"""Apply mixins to a class instance after creation"""
obj.__class__ = type(obj.__class__.__name__, (cls, obj.__class__),{})
关于python - 在运行时替换 python Mixin 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47753873/