我正在使用Hippo Mocks取得巨大成功,但我有一种情况,我无法弄清楚如何正确设置。测试中的代码看起来像这样:
auto firstName = record.at("firstName").getValue();
auto lastName = record.at("lastName").getValue();
其中IRecord::at()
返回IColumn&
,其中包含纯虚拟getValue()
方法。我正在尝试使用模拟版Irecord
和IColumn
来测试我的代码:
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”。
跟着tutorial,我试图限制“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()
次来电获得“约翰”。
问:是否可以重复使用IColumn
界面,并告诉Hippo Mocks按照我的需要为每个getValue()
调用返回不同的值,或者我是否卡在创建为每个参数单独IColumn
模拟?注意:我的实际实现将有两个以上的参数,因此重用IColumn
模拟减少了每个单元测试的大量设置。
答案 0 :(得分:2)
我不确定您的情况是什么问题,但是当我使用version form the git repoitory
运行以下代码时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"));