我想将字符串“Device Name”传递给方法的void *
指针参数,然后将其检索到字符数组。
为此,我已完成如下所示。
在这里,我创建了一个实现此目的的动作。
ACTION_P(SetArg2ToChar, value) {*static_cast<char*>(arg2) = *value; }
要调用/模拟的实际方法
bool getDictItem(WORD wIndex, BYTE bSubIndex, void * pObjData, DWORD dwLength, CSdo& sdo)
我的模拟方法
MOCK_METHOD5(getDictItem,
bool(WORD wIndex, BYTE bSubIndex, void * pObjData, DWORD dwLength, CSdo& sdo));
代码中的被称为
if( !can.getDictItem(wIndex, bSubIndex, pObjData, dwLength, tSdo) )
我想将一个字符串传递给此pObjData
(列表中的第三个参数)。
在我的谷歌测试中,我这样做。
char szDeviceName[30]= {0};
snprintf(szDeviceName, sizeof(szDeviceName), "%s", "Device Name" );
EXPECT_CALL( mockCan, getDictItem(_,_,_,_,_) )
.WillOnce(DoAll(SetArg2ToChar(szDeviceName),
Return(true)))
.RetiresOnSaturation();
/* Call a real method within which this mock method is called */
如果我尝试使用“SetArgPointee&lt; 2&gt;”设置此参数(pObjData)直接,我得到以下错误。
错误:'void '不是指针对象类型*
因此我正在尝试使用ACTION_P
现在有了这个实现,我只得到szDeviceName
变量的第一个字母(进入这个pObjData
),即在此模拟对象之后,真实代码流中的“D”后跟29 0'调用。
我想在这个void *
争论中设置完整的字符串名称。
我参考了下面这个问题并且能够在这方面取得进展。但是我无法传递完整的字符串。 How to set, in google mock, a void* argument to a set of values?
任何有关此信息都会有所帮助。
答案 0 :(得分:1)
然后,您可以调用函数(或方法)并复制参数。
测试的源文件中有这样的东西:
int invokedPObjData;
bool FakeGetDictItem(WORD wIndex, BYTE bSubIndex, void * pObjData, DWORD dwLength, CSdo& sdo)
{
// copy data. here I assumed it is an int
invokedPObjData = *static_cast< int* >( pObjData );
return true; // or whatever makes sense
}
在测试中:
EXPECT_CALL( mockCan, getDictItem(_,_,_,_,_) )
.WillOnce(Call(FakeGetDictItem))
.RetiresOnSaturation();
然后在测试中检查需要检查的内容。
答案 1 :(得分:1)
ACTION_P
方法基本上没问题。但是当你处理一个C字符串时,你不能只使用赋值操作(它只复制第一个字符),而是你应该使用像ACTION_P(SetArg2ToCharWithSizeArg3, value) { strcpy_s(static_cast<char*>(arg2), arg3, value); }
这样的字符串复制函数(我无法做到)。抵制轻微重命名行动。)
答案 2 :(得分:1)
我最近有类似的需求,并将其作为通用解决方案提出来。它基于内置SetArgPointee
并具有相同的语法:
template <size_t N, typename A>
class SetArgumentPointeeVoidAction {
public:
explicit SetArgumentPointeeVoidAction(const A& value) : value_(value) {}
void operator=(SetArgumentPointeeVoidAction const&) = delete;
template <typename Result, typename ArgumentTuple>
void Perform(const ArgumentTuple& args) const
{
::testing::StaticAssertTypeEq<void, Result>();
::testing::StaticAssertTypeEq<void*,
std::decay<decltype(::testing::get<N>(args))>::type>();
*static_cast<A*>(::testing::get<N>(args)) = value_;
}
private:
const A value_;
};
/**
* \brief Sets a \c void* output argument to the contents of the
* supplied object. It's on you to ensure this is safe.
* \tparam N The argument index.
* \tparam T The real argument type.
* \param x The argument to assign to the output argument.
* \return A GMock Action that performs the requested assignment.
* \note Use \c SetArgPointee when it's not a \c void*.
*/
template <size_t N, typename T>
::testing::PolymorphicAction< SetArgumentPointeeVoidAction<N, T> >
SetArgPointeeVoid(const T& x)
{
return ::testing::MakePolymorphicAction(
SetArgumentPointeeVoidAction<N, T>(x));
}
如果你尝试在不是void*
的参数上使用它,它会给你一个编译错误,所以只要你确保提供正确的参数它就应该是相对安全的。
也可以使用ACTION_TEMPLATE
来实现这一点,::std::tr1::get
虽然有点短,但它会生成未使用的参数警告,这可能会令人恼火。
(在旧版GMock中,您可能必须使用::testing::get
而不是void*
。)
留给读者练习:可以通过完美转发来增强这一功能,以便进行移动构建和移动分配,从而提高效率。虽然如果您将{PODs以外的任何内容传递给 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
,那么您可能做错了。
答案 3 :(得分:0)
以下是使用ACTION_TEMPLATE的示例,该示例允许将字符串分配给!important
,以供参考...
void *
答案 4 :(得分:0)
请找到使用invoke方法在类中设置Void Pointer变量的步骤。
//Actual Function under Test
void testFunction(void)
{
uint16 Frequency;
uint8 PwmId;
uint8 DutyCycle;
Frequency = PORTEXTENDER_ZERO;
PwmId = PORTEXTENDER_ZERO;
DutyCycle = PORTEXTENDER_ZERO;
//for this mock is available and we need to set value of Ex. PwmId
IncCom_ReceiveSignal(SCC_PORT_EXTENDER_PWM_C_SET_PWM_Id, &PwmId);
if((PwmId <= PORTEXTENDER_NUM_PWM_CHANNELS) && (DutyCycle <= 100))
{
}
// Actual Defination of mock ..where we have to set void pointer
void mock_defination(PortExtender_C_SignalId_e SignalId, void* SignalDataPtr)
{
}
//cpp Test class
class testClass : public :: testing :: Test
{
protected:
/* Fixture tear down */
virtual void TearDown()
{
}
uint8 testval1{1};
public:
void setTestvalue(uint8 val) // if we want to set multiple time
{
testval1= val;
}
void test1(PortExtender_C_SignalId_e SignalId, void* SignalDataPtr) //this is method to invoke from test_F
{
* (uint8*)SignalDataPtr =testval1;
}
}
//Test Case
TEST_F(testClass,
testcase_PortExtender_CompStatusResponse_ifConditionSatisfied)
{
setTestvalue(1); //To Set Value
EXPECT_CALL(m_portExtender_SomeIpMock,m_C_Signal(SCC_PORT_EXTENDER_C_COMPONENT_STATUS_HostApplStat,_))
.WillOnce(Invoke(this,&testClass::test1));
}