As I mentioned in the comments, one way to test a single method without having to create an instance is:
MyClass.my_method(any_object_with_my_attribute)
The problem with this, as with both options in quamrana's answer, is that we have now expanded the scope of any future change just because of the tests. If a change to my_method
requires access to an additional attribute, we now have to change both the implementation and something else (the SuperClass
, the MockMyClass
, or in this case any_object_with_my_attribute_and_another_one
).
Let's have a more concrete example:
import json
class MyClass:
def __init__(self, filename):
with open(filename) as f:
data = json.load(f)
self.foo = data.foo
self.bar = data.bar
self.baz = data.baz
def my_method(self):
return self.foo ** 2
Here any test that requires an instance of MyClass
. is painful because of the file access in __init__
. A more testable implementation would split apart the detail of how the data is accessed and the initialisation of a valid instance:
class MyClass:
def __init__(self, foo, bar, baz):
self.foo = foo
self.bar = bar
self.baz = baz
def my_method(self):
return self.foo ** 2
@classmethod
def from_json(cls, filename):
with open(filename) as f:
data = json.load(f)
return cls(data.foo, data.bar, data.baz)
You have to refactor MyClass("path/to/file")
to MyClass.from_json("path/to/file")
, but wherever you already have the data (e.g. in your tests) you can use e.g. MyClass(1, 2, 3)
to create the instance without requiring a file (you only need to consider the file in the tests of from_json
itself). This makes it clearer what the instance actually needs, and allows the introduction of other ways to construct an instance without changing the interface.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…