1

Hippo Mocks を使用して大成功を収めていますが、適切に設定する方法がよくわからないという状況があります。テスト中のコードは次のようになります。

auto firstName = record.at("firstName").getValue();
auto lastName = record.at("lastName").getValue();

Whereは、純粋仮想メソッドを持つ をIRecord::at()返します。およびのモック バージョンでコードをテストしようとしています。IColumn&getValue()IrecordIColumn

auto mockRec = mocks.InterfaceMock<IRecord>();
auto mockCol = mocks.InterfaceMock<IColumn>();

私はうまく期待を設定することができfirstNameます:

mocks.OnCall(mockRec, IRecord::at).With("firstName").Return(std::ref(*mockCol));
mocks.OnCall(mockCol, IColumn::getValue).Return(std::string("John")));

IColumnしかし、次の期待のためにモックを再利用したいと思いlastNameます。

mocks.OnCall(mockRec, IRecord::at).With("lastName").Return(std::ref(*mockCol));
mocks.OnCall(mockCol, IColumn::getValue).Return(std::string("Doe")));

しかし、これを実行すると、Hippo Mocks は両方のgetValue()呼び出しに対して "John" を返します。

チュートリアルに従って、「firstName」と「lastName」の呼び出しの順序を制限しようとしました。

auto& firstCall = mocks.OnCall(mockRec, IRecord::at).With("firstName").Return(std::ref(*mockCol));
mocks.OnCall(mockCol, IColumn::getValue).After(firstCall).Return(std::string("John")));

auto& lastCall = mocks.OnCall(mockRec, IRecord::at).With("lastName").Return(std::ref(*mockCol));
mocks.OnCall(mockCol, IColumn::getValue).After(lastCall).Return(std::string("Doe")));

しかし、私はまだ両方のgetValue()呼び出しで「ジョン」を受け取ります。

Q:インターフェイスを再利用して、IColumnHippo Mocks に必要な呼び出しごとに異なる値を返すように指示することはできますか? それとも、パラメーターごとgetValue()に個別のモックを作成するのに行き詰まっていますか? IColumn注: 私の実際の実装には 2 つ以上のパラメーターがあるため、IColumnモックを再利用すると、各単体テストのセットアップが大幅に削減されます。

4

1 に答える 1

2

あなたの場合の問題が何であるかはわかりませんが、次のコードをgit リポジトリからのバージョンで実行すると

struct IColumn {
    virtual std::string getValue() = 0;
}; 

struct IRecord {
    virtual IColumn& at( std::string ) = 0;
};

void main()
{
    MockRepository mocks;

    auto mockRec = mocks.Mock<IRecord>();
    auto mockCol = mocks.Mock<IColumn>();

    auto& firstCall = mocks.OnCall(mockRec, IRecord::at).With("firstName").Return(std::ref(*mockCol));
    mocks.OnCall(mockCol, IColumn::getValue).After(firstCall).Return(std::string("John"));

    auto& lastCall = mocks.OnCall(mockRec, IRecord::at).With("lastName").Return(std::ref(*mockCol));
    mocks.OnCall(mockCol, IColumn::getValue).After(lastCall).Return(std::string("Doe"));

    std::cout << mockRec->at("firstName").getValue() << " " 
              << mockRec->at("lastName").getValue() << "\n";
}

正しい出力が得られます。

John Doe

私はほとんどいつも使っていることがわかります

mocks.autoExpect = false;

しかし、この場合、違いはありません。

編集:

さらに柔軟性が必要な場合は、次のようにすることができます。

std::vector<IColumn*> cols;

cols.push_back( mocks.Mock<IColumn>() );
cols.push_back( mocks.Mock<IColumn>() );

mocks.OnCall(mockRec, IRecord::at).With("firstName")
     .Return(std::ref(*cols[0]));
mocks.OnCall(mockRec, IRecord::at).With("lastName")
     .Return(std::ref(*cols[1]));

mocks.OnCall(cols[0], IColumn::getValue)
     .Return(std::string("John"));
mocks.OnCall(cols[1], IColumn::getValue)
     .Return(std::string("Doe"));

これは、呼び出しの任意の順序で機能します。または、使用することもできますDo

std::map<std::string, IColumn*> map;

map["firstName"] = mocks.Mock<IColumn>();
map["lastName"] = mocks.Mock<IColumn>();

mocks.OnCall(mockRec, IRecord::at)
     .Do( [&map]( std::string& key){ return std::ref(*map[key]); } );

mocks.OnCall(map["firstName"], IColumn::getValue)
     .Return(std::string("John"));
mocks.OnCall(map["lastName"], IColumn::getValue)
     .Return(std::string("Doe"));
于 2013-03-09T17:47:26.380 に答える