googlemockとC++での依存性注入を使って単体テストを行うのは難しいです。モックと依存性注入は、コードテストを大幅に簡素化しますが、仮想メソッドに大きく依存しています。他の言語のクラスはデフォルトで仮想メソッドを使用しますが、C++の場合はそうではありません。私はC + +を使用して低オーバーヘッドのパフォーマンス測定フレームワークを作成しているので、すべての単一のクラスをインターフェース(純粋な仮想メソッドあり)から継承することは望ましい選択肢ではありません。私は次のことを行うことができ、このクラスをテストするにはCockでの擬似と依存性注入
struct event_info { /* ... */ };
template<typename Event>
class event_manager {
public:
event_manager(const std::vector<event_info>& events) {
std::transform(begin(events), end(events),
std::back_inserter(events_),
[](const event_info& info) { return Event{info}; });
}
void read() {
for (auto& e : events_)
e.read();
}
// ...
private:
std::vector<Event> events_;
// ...
};
:
具体的には、私は、次の1などのオブジェクトのコレクションが含まれているテストクラスで問題を抱えている
class mock_event {
public:
MOCK_METHOD0(read, void());
};
TEST(event_manager, test) {
event_manager<mock_event> manager;
// ...
}
しかし、 mockオブジェクトの期待値を設定することはできず、googlemockのモックオブジェクトはコピーできません(したがって、std::transform
への呼び出しはコンパイルに失敗します)。
この問題を解決するには、テスト時に代わりにポインタ(event_manager<mock_event*>
)を使用して、event_manager
コンストラクタにファクトリを渡します。しかし、これはe.read()
のような呼び出しのためにコンパイルされません(テスト時にはe->read()
になるはずです)。
次に、タイプ特性を使用して、参照が返されたばかりの参照が返され、ポインタが指定されている場合はポインタを逆参照します(dereference(e).read()
など)。しかし、これはちょっとした複雑さを増やしてしまい、良い解決策のように見えません(特に、オブジェクトのコレクションを含むすべてのクラスをテストする必要がある場合)。
これはもっと良い解決策があるのだろうか、まさに擬似と依存性注入がC++にはあまり適していないということです。
これは良い質問です!私は答えを期待する。私の理解では、 'event_manager'を少し修正しようとするかもしれません。' std :: vector> 'を使ってください。おそらくこれで問題は解決します。しかし、私はそれが動作するかどうかを確信していませんでした。 –
Mine
@Mine 'unique_ptr'とファクトリを使って(あるいは単にユーザが' unique_ptrを追加できるようにするためにインタフェースを変更するだけで ')動作するはずです。しかし、私は生産現場でポインタを格納する必要があります(テスト中だけでなく)。私はそれを避けるための解決策を探しています。 –
betabandido
うん、私はあなたが生産とテストコードの両方のポインタ( 'unique_ptr')ボットを格納できることを意味します。それは問題ではありません。 – Mine