user1228352
user1228352

Reputation: 569

Mocking standard library functions using gmock

Following is the function which I want to unit test:

void sampleFunc()
{
   FILE *file = fopen(path, "rb");
   if (!file) {
     std::cout << "File couldn't be opened!" << std::endl;
   }
   const int bufSize = 32768;                                              
   unsigned char *buffer = (unsigned char*) malloc(bufSize);               
                                                    
   if (!buffer) {                                                           
     fclose(file);                                                       
     std::cout << "Failed to allocate buffer for SHA256 computation." << std::endl;
   }
   // ..
   // Read file into buffer
   // ..
}

As shown in the code, my function uses many standard library functions. So am I supposed to mock standard library functions or make actual calls to functions?

Upvotes: 0

Views: 2038

Answers (1)

Jarod42
Jarod42

Reputation: 217075

What you might do to test your function:

class IFileManager
{
public:
    virtual ~IFileManager() = default;

    // You could even improve interface by returning RAII object
    virtual FILE* fopen(const char* path, const char* mode) = 0;
    virtual void fclose(FILE*) = 0;
    // ...
};

class FileManager : public IFileManager
{
public:
    FILE* fopen(const char* path, const char* mode) override { return ::fopen(path, mode); }
    int fclose(FILE* f) override { return ::fclose(f); }
    // ...
};

class IAllocator
{
public:
    virtual ~IAllocator() = default;

    virtual void* allocate(std::size_t) = 0;
    virtual void deallocate(void*) = 0;
};

class Allocator : public IAllocator
{
public:
    void* allocate(std::size_t size) override { return malloc(size); }
    void deallocate(void* p) override { free(p); }
};

Your function becomes:

void sampleFunc(IFileManager& fileManager, IAllocator& allocator)
{
   FILE *file = fileManager.fopen(path, "rb");
   if(!file) {
     std::cout << "File couldn't be opened!" << endl;
     return;
   }
   const int bufSize = 32768;
   unsigned char *buffer = (unsigned char*) allocator.allocate(bufSize);

   if(!buffer) {
     fileManager.fclose(file);
     std::cout << "Failed to allocate buffer for SHA256 computation." << std::endl;
     return;
   }
   // Read file into buffer
   // ...
}

Finally, you can easily mock IFileManager and IAllocator.

Without that interface, you would have to make standard function behave as you expect, which is not necessary simple feasible (wrong path, limit memory (which limit))

Care also that implementation might have more limitations. that the one from interface (MAX_PATH, non-regular files, UNC path)

Upvotes: 5

Related Questions