web-dev-qa-db-ja.com

Googleモックによる抽象クラスのユニットテスト(gmock / gtest)(C ++)

抽象クラスをテストしたい:

  1. サブクラスでオーバーライドする必要がある純粋な仮想メソッド
  2. 純粋な仮想メソッドを使用する非純粋な仮想メソッド( この質問 とは対照的に)
class Fu
{
  public:
    virtual void func(int count, std::string data)
    {
        for(int i = 0; i < count; i++)
        {
            pureFunc(data);
        }

    }
    virtual void pureFunc(std::string data) = 0;
}

次にfuncをテストするために、引数countを使用してpureFunc dataを呼び出すことを確認します。私が行ったことは、Fuをサブクラス化し、Mockを作成することです。

class TestFu : public Fu
{
  public:
    virtual void pureFunc(std::string data) override {};
}

class MockFu : public TestFu
{
  public:
    MOCK_METHOD1(pureFunc, void(std::string));
}

そしてテストするために私は次のことをします:

MockFu mock_fu;
EXPECT_CALL(mock_fu, pureFunc("test"))
.Times(10);

mock_fu.func(10, "test");

しかし、私は上記が有効なパターンかどうか疑問に思っていました。私の心配は、クラスではなくモッククラスをテストしていること、またはそれが非抽象サブクラスであることです。

総括する:

  1. 上記のパターンは有効ですか?はいの場合、モックオブジェクトをテストしても問題ありませんか?どうすれば目標を達成できますか?
  2. 一般に、クラスの一部をモックして他の部分を単体テストすることは有効な方法ですか?もしそうなら、そうするための一般的な慣行は何ですか?
1
pooya13

あなたはここでかなり多くのことを尋ねていますが、あなたが説明することについて私の意見を共有させてください。

モッククラスの一般的な使用法は、別のクラスをテストするために必要であり、モッククラスの状態が変更されているかどうかを確認する必要がある場合です(インターフェースのより重い実装の代わりに)。

あなたが説明するケースはもちろん有効ですが、テスト自体は役に立たないと主張したいと思います。典型的な例では、pureFuncはプライベートであると想定しますが、それほど重要ではありません。現在テストしているのは実装であり、動作ではありません。テストする必要があるのは、funcが行うことです(つまり、何かを返すか、クラスの状態を変更することによって)。

より明確にするために。あなたの例では、forcループでfunc runをcount/2にして、コードをpureFunc自体で2回実行することができます(奇数では機能しませんが、引数として考慮してください。単体テストは失敗しますが、 、オブジェクトの状態は同じです。ユニットテストが失敗し始めることなく、クラスと実装を変更できるようにする必要があります。実装を変更するたびにユニットテストを変更する必要がある場合は、何か問題が発生しています。

代わりに何ができますか?さて、あなたはあなたの抽象クラスの実装を持っています。 funcをテストして、期待どおりに機能するかどうかを確認できます。 (実際に公開されている場合は、pureFunc)。

2
Bernhard