最近、Python モジュールの Pytest を使用して単体テストを作成する必要がありました。モジュールには、コンストラクター内で他のクラスが初期化されるクラスが含まれています。
いつものように、各クラス メソッドのテストを簡単に作成できるように、このクラスのフィクスチャを作成しました。この時点で、コンストラクターで開始されたさまざまなクラスをモックしようとしたときに、いくつかの問題に遭遇しました。モックは機能せず、これらのクラスのインスタンスはまだ作成されていました。
いくつかの調査を行い、オンラインで見つけたいくつかの異なるソリューションを組み合わせた後、クラスを模擬する方法を共有したいと思います。
これが私がモックしようとしたクラスの例です:
class ClassA: def __init__(self): self.class_b = ClassB() self.class_c = ClassC() self.count = 0
テスト中にこのクラスのすべてのフィールドに値を設定したいと考えています。この値は None またはクラス モックにすることができますが、クラス ClassB と ClassC の開始は望ましくありません。
私たちの場合、self.class_b と self.class_c をモックにすることにしましょう:
@pytest.fixture def mock_class_b(): class_b = Mock(spec=ClassB) return class_b @pytest.fixture def mock_class_c(): class_c = Mock(spec=ClassC) return class_c
したがって、私たちの目的を果たすこのクラスのフィクスチャは次のようになります:
@pytest.fixture def class_a_mock(mock_class_b, mock_class_c): with patch.object(target=ClassA, attribute="__init__", return_value=None) as mock_init: class_a = ClassA() class_a.class_b = mock_class_b class_a.class_c = mock_class_c class_b.count = 0 return class_a
重要な部分は、Python の Unittest.mock モジュールにある patch.object 関数の使用方法です。これは、特定のオブジェクトの属性をモックまたは別の値に一時的に置き換えるためのテストで使用されます。
引数
このようにして、フィクスチャ内にモック化された変数を作成できます。
patch.object
このチュートリアルは、何らかの理由でクラス A のコードを変更できない場合に備えて作成しました。ただし、一般的には、ロジックを変更するのではなく、よりテストしやすくするために、可能であればコードを変更することをお勧めします。 .
クラス A を変更してテストしやすくする方法の例をいくつか示します:
オプション 1: クラス B とクラス C のインスタンスをパラメータとして渡します。
こうすることで、フィクスチャを作成するときに、インスタンスの代わりにモックを渡すことができます。
class ClassA: def __init__(self, class_b_instance, class_c_instance): self.class_b = class_b_instance self.class_c = class_c_instance self.count = 0
オプション 2: テスト モードを示すブール変数を作成します。
このようにして、クラス A のどのフィールドが開始時に値を取得するか取得しないかを決定できます。
class ClassA: def __init__(self, test_mode=False): if not test_mode: self.class_b = ClassB() self.class_c = ClassC() self.count = 0
オプション 3: 別のメソッドでクラスを開始します。
このアプローチにより、テスト モジュールで set_class_variables の呼び出しを回避するという選択肢が得られます。
class ClassA: def __init__(self): self.class_b = None self.class_c = None self.count = None def set_class_variables(self): self.class_b = ClassB() self.class_c = ClassC() self.count = 0
これがお役に立てば幸いです! :)
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3