Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can i mock a member function of A class in a B class's function? #309

Open
git45016683 opened this issue Aug 4, 2023 · 3 comments
Open

Comments

@git45016683
Copy link

This is a common scenario:
class B has an A object, so class B member function can call class A member function with A object.
so how can i mock class A member function when i perform unit testing on class B member function?
example code like below:

class memberFuncHeader
{
public:
	void vOutputValueByPointer(char* p_cStr)
        {
            p_cStr[0] = 'o'; p_cStr[1] = 'r'; p_cStr[2] = 'i';
	    p_cStr[3] = 'g'; p_cStr[4] = 'i'; p_cStr[5] = 'n';
        }
}

class callMemberFunc
{
public:
  int iTest_OutputValueByPointer(char* p_cStr){
        m_pObj->vOutputValueByPointer(p_cStr);
	return 0;
  }
public:
	memberFuncHeader* m_pObj;
}

the unit test code like below:

class memberFuncMock {
public:
	MAKE_MOCK1(vOutputValueByPointer, void(char*));
};
memberFuncMock memberMock;

callMemberFunc* g_pCallMemberFunc = new callMemberFunc();

int funcCall_OutputValueByPointer(char* p_pcStr) {
	int l_iRet = -1;
	char l_acStr[256] = {0};
	l_iRet = g_pCallMemberFunc->iTest_OutputValueByPointer(l_acStr);
	memcpy(p_pcStr, l_acStr, 256);
	return l_iRet;
}

TEST_CASE("demo2mockMemberFunc0") {
	char* l_pStr = new char[256];
	memcpy(l_pStr, "HELLOWORLD", strlen("HELLOWORLD"));
	REQUIRE_CALL(memberMock, vOutputValueByPointer(_)).LR_SIDE_EFFECT(memcpy(_1, l_pStr, strlen(l_pStr)));

	char l_acStr[256] = { 0 };
	int l_iRet = funcCall_OutputValueByPointer(l_acStr);
	CHECK(l_iRet == 0);
	CHECK(memcmp(l_acStr, "HELLOWORLD", strlen("HELLOWORLD") == 0));
}

I expect iTest_OutputValueByPointer call vOutputValueByPointer mock function and l_acStr equal “HELLOWORLD”, but iTest_OutputValueByPointer actually call class memberFuncHeader function then output 'origin' to l_acStr.

can do this with trompeloeil?
and i push the demo code at demo

@rollbear
Copy link
Owner

You need to make the A member accessible in the test so that you can place an expectation on it. One traditional technique for this is dependency injection, i.e. you create your B with the mocked A for the test.

@git45016683
Copy link
Author

Yeah, I know what you mean, but that's a real huge workload, because there's a lot of historical code (T_T). And they are running at product....
So, i want to found some solution that can integrated unit testing without requiring too many source code changes。
There are many codes like demo in historical code。Although not the best, but it work。 So i can not change every class to dependency injection。
Thanks。

@rollbear
Copy link
Owner

rollbear commented Aug 29, 2023

Well, the library can only work within the rules of the language. For this to work you need:

  1. To ensure that in the test, the member m_pObj points to a mock object.
  2. Access to the mock object from the test code, and its type known, at compile time, in the test to be a mock.

With those you can place expectations on the mock and test your code. If those are not acceptable, then I'm afraid I cannot help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants