On ELF systems you can use elf_hook to temporarily replace the real versions of various functions with your own mocked versions.
It allows you to redirect calls to any function from within a shared library to your own arbitrary function.
- Create a shared library containing the code under test
 
- In your test load the shared library dynamically (
dlopen) 
- Redirect the symbols you want to mock to your test functions (
elf_hook) 
- Now any calls to the real function within the library (the code under test) will be redirected to your mocked function
 
A plus for this method is that you can still call the original function when required.
- If for some tests you want to have the call to, eg 
getaddrinfo, succeed, you can call the system version. 
- In other tests you can use your own mocked version, eg 
mocked_getaddrinfo, and have it return whatever you want. 
- You can create as many 
mocked_getaddrinfo functions as you want, to test multiple scenarios 
elf_hook has the following signature:
void* elf_hook(char const* library_filename, 
               void const* library_address, 
               char const* function_name, 
               void const* substitution_address);
You would use it like this:
#include <dlfcn.h>
#include "elf_hook.h"
void do_stuff(); // from the library under test (do_stuff calls getaddrinfo)
// our mocked function which will alter the behaviour inside do_stuff()
int mocked_getaddrinfo(const char* node, 
                       const char* service,
                       const struct addrinfo* hints,
                       struct addrinfo** res)
{
    // return a broken value to test a getaddrinfo failure
    return 42;
}
// another version which actually calls the real function
int real_getaddrinfo(const char* node, 
                     const char* service,
                     const struct addrinfo* hints,
                     struct addrinfo** res)
{
    // the real getaddrinfo is available to us here, we only replace it in the shared lib
    return getaddrinfo(node, service, hints, res);
}
int main()
{
    const char* lib_path = "path/to/library/under/test.so";
    // load the library under test
    void* lib_handle = dlopen(lib_path, RTLD_LAZY);
    // test 1: getraddrinfo is broken
    //--------------------------------
    // replace getaddrinfo with our 'mocked_getaddrinfo' version
    elf_hook(lib_path, LIBRARY_ADDRESS_BY_HANDLE(lib_handle), 
             "getaddrinfo", mocked_getaddrinfo);
    // call a function in the library under test where getaddrinfo fails
    do_stuff();
    // test 2: getraddrinfo is the system version
    //--------------------------------
    // replace getaddrinfo with our 'real_getaddrinfo' version 
    elf_hook(lib_path, LIBRARY_ADDRESS_BY_HANDLE(lib_handle), 
             "getaddrinfo", real_getaddrinfo);
    // call the same function in the library, now getaddrinfo works
    do_stuff();
    dlclose(lib_handle);
    return 0;
}
Any call to getaddrinfo from within the library under test will now call mocked_getaddrinfo.
A comprehensive article by the elf_hook author, Anthony Shoumikhin, is here.