2016-11-15 4 views
6

時々、テスト用に特定のコンストラクタを用意する必要がある場合があります。このようなコンストラクタを強制的にテストコードでのみ使用する方法はありません。 これがC++ 11/14で達成可能かどうか疑問に思います。例えば、特定のコードでのみ使用される特定のコンストラクタを他の場所に強制しない

class A { 
public: 
    A() = default; // used only in test code 
} 
class A_Test : public ::testing::Test { 
private: 
    A a; // it is ok. 
}; 
class A_Production { 
private: 
    A a; // compiler error 
} 

私はfriendデコレータを使用してアクセスを制限するprotected内の特定のコンストラクタを置くことを想像できます。レガシーコードには他の既存の友人もいます。 C++ 1xで保護されたカスタム指定子を作ることは可能ですか?

+0

ラッパークラス(ES)何とか自分の要件に応じて、またはあなたがそのようプロジェクトの構造を再設計本当にその問題はありません。あなたがこの問題を抱えているかどうかは、あなたが悪い設計をしているからです。 – nbro

+2

まあ、これはかなり合理的な要件だと思います。 – pepero

+1

テストコードがプロダクションコードと異なるコードパスを実行している場合、_probably_はあまり良いテストコードではありません。 – ildjarn

答えて

1

私はそれを行ういくつかの方法を考えることができます。

  1. コンストラクタprotectedを、それを使用するテストサブクラスのみで作成します。

  2. は、パラメータとしてこのクラスへの参照を取るコンストラクタを宣言し、class TestClassThatShouldNotBeUsedInProductionCode;、いくつかのダミーのクラスに前方宣言を追加します。

    A::A(/* other constructor arguments */, 
         const TestClassThatShouldNotBeUsedInProductionCode &) 
    

このコンストラクタは、単純に完全にこのパラメータを無視することができます。あなたのテストモジュールはこのダミーの空のクラス:class TestClassThatShouldNotBeUsedInProductionCode {};を定義し、それを使ってAクラスを構築することができます。あなたのテストモジュールだけがこのコンストラクタを使用することができます。そしてその名前は、これが何であるかを明確にします。実際のコードとテストコードのどちらかをC++で定義する方法はありません。誤って違反しにくい明確なポリシーを実装したいだけです。

スタンドアロンクラスを前方宣言する代わりに内部クラスを使用するなど、いくつかのバリエーションが可能です。内部クラスは、テストコードによってのみインスタンス化することができます。

#define private public 
#include "ClassA.h" 

// ready for testing :) 
+1

これは回避策です。この問題が発生するかどうかは不明です。 – nbro

-1

ConstructorKeyによって提供されたインダイレクションによって、Aは、そのインターフェイスで、ConstructorKeyの友人にアクセスすることを望みます。これが可能であるかない場合、私はわからないんだけど、回避策は、1つ(または複数)を作成することです

class A { 
    class ConstructorKey { 
    friend class A_Test; 
    private: 
    ConstructorKey() {}; 
    ConstructorKey(ConstructorKey const&) = default; 
    }; 
public: 
    // Whoever can provide a key has access: 
    explicit A(ConstructorKey); // Used only in test code 
}; 

class A_Test : public ::testing::Test { 
private: 
    A a {ConstructorKey{}}; // OK 
}; 

class A_Production { 
private: 
    A a {ConstructorKey{}}; // Compiler error 
}; 
+0

これは不正な形式であり、一部のコンパイラがそのことをキャッチします – sp2danny

+0

ODRに違反するのは良いアドバイスではありません。; - ] – ildjarn

+0

非常に悪い考えです。これがうまくいくという保証はありません。 1つは、レイアウトが変わるかもしれないことです。 – user3721426

3

あなたはPasskey Idiomを使用できます:

代わりに直接友情の、あなたはA_TestからAへのアクセスを制限するのテストを行うのcppファイルに代わるものとして

関連する問題