Locking free function

I am stuck in a problem and cannot find a solution.

I am using VS2005 SP1 to compile the code.

I have a global function:

A* foo(); 

I have a mock class

 class MockA : public A { public: MOCK_METHOD0 (bar, bool()); ... }; 

Access in the sources is as follows: foo()->bar() . I cannot find a way to mock this behavior. And I can’t change the sources, so the solution in the Google Mock Cook Book is out of the question.

Any help or pointers in the right direction would be greatly appreciated. :)

+6
source share
2 answers

No, this is not possible without changing the sources or casting your own version of foo() related to the executable code.


From the FAQ in GoogleMock it says

My code calls a static / global function. Can I mock this?

You can, but you need to make some changes.

In general, if you need to mock a static function, it means that your modules are too tightly coupled (and less flexible, less reusable, less verifiable, etc.). You are probably better off defining a small interface and calling a function through that interface, which can then be easily ridiculed. At first it works a little, but usually pays for itself quickly.

This Google Testing post blog talks about it superbly. Check this.

Also from Cookbook

Docking free features

You can use Google Mock to bully a free function (i.e. a C-style function or a static method). You just need to rewrite your code in order to use the interface (abstract class).

Instead of directly calling a free function (for example, OpenFile), enter an interface for it and create a specific subclass that calls the free function:

 class FileInterface { public: ... virtual bool Open(const char* path, const char* mode) = 0; }; class File : public FileInterface { public: ... virtual bool Open(const char* path, const char* mode) { return OpenFile(path, mode); } }; 

Your code must talk to FileInterface to open the file. Now it's easy to mock a feature.

This may seem like a lot of trouble, but in practice you often have several related functions that you can put in the same interface, so the syntax overhead for each function will be significantly lower.

If you are concerned about the performance overhead of virtual functions, and profiling confirms your concern, you can combine this with a recipe for ridiculing non-virtual methods.


As you mentioned in your comment that you really provide your own version of foo() , you can easily solve this by having a global instance of another mock class:

 struct IFoo { virtual A* foo() = 0; virtual ~IFoo() {} }; struct FooMock : public IFoo { FooMock() {} virtual ~FooMock() {} MOCK_METHOD0(foo, A*()); }; FooMock fooMock; // Your foo() implementation A* foo() { return fooMock.foo(); } TEST(...) { EXPECT_CALL(fooMock,foo()) .Times(1) .WillOnceReturn(new MockA()); // ... } 

Remember to clear all call waiting after running each test case.

+9
source

Of course, the answer explaining the solution according to the GTest / GMock documentation could not be more correct.

But I would like to add a temporary quick and dirty approach. It should be applicable to cases where you want to get obsolete C / C ++ code under the test as quickly and non-invasively as possible. (Just to continue with corrections, refactoring, and better testing as soon as possible after.)

So, to make fun of the free void foo(int) function that appears in some test code, you only make the following adaptations in the source file:

 #if TESTING #define foo(param) // to nothing, so calls to that disappear #endif // ... code that calls foo stays untouched and could be tested 

The TESTING macro, indicating that the code runs under the test, does not come with GTest / GMock - you need to add it for testing purposes yourself.

The possibilities are pretty limited, but you can also build something useful for return types like A* in the sample question.

Unfortunately, this is also not a solution without changing the code. If it’s really necessary, you can use Google for “link seams”. But I suggest that this can be quite a hassle in practice. And it may even be impossible at all in many / most cases ?!

0
source

Source: https://habr.com/ru/post/982162/


All Articles