I was wondering is it possible to mock a C function using the Python mock library and how?
To make a unit test for a C function in Python I use the shared library, but I can't mock one function in order to pass the test. Tests work fine when there is no need to use mock.
So my question is: Is it possible to mock a C function using Python mock and how?
Here is an example of source code.
//read_sensor.c
#include <stdint.h>
#include "read_sensor.h"
uint8_t read_sensor (void)
{
return 0xff;
}
//event_report.c
include <stdint.h>
#include <string.h>
#include "event_report.h"
#include "read_sensor.h"
#define TRUE 1
#define FALSE 0
extern char status ;
extern uint8_t flag;
void read_distance(void)
{
uint8_t count;
uint8_t value;
uint8_t flag_count = 0;
for (count = 0; count < 3; count ++)
{
value = read_sensor();
if ( value < 100 )
{
flag_count++;
}
}
if ( flag_count == 3)
{
flag = TRUE;
}
else
{
flag = FALSE;
}
}
and the test is here
import ctypes
from ctypes import *
import mock
import unittest
TRUE = 1
FALSE = 0
class TestClass(unittest.TestCase):
def setUp(self):
print "\nSetUp\n"
self.event=ctypes.CDLL('d:/test_pytest/test_sensor_report/event_report.so')
def tearDown(self):
print "tearDown\n"
def test_1_flag_should_be_true_when_readed_distance_is_0(self):
expected_flag = TRUE
self.event.read_sensor = MagicMock(return_value = 0)
#calling function under test
result = self.event.read_distance()
print result
#testing assertion
assert expected_flag == result
After inspecting with inspect.getmembers()
I get the following:
[('_FuncPtr', <class 'ctypes._FuncPtr'>), ('__class__', <class
'ctypes.CDLL'>), ('__delattr__', <method-wrapper '__delattr__' of
CDLL object at 0xffa87eec>), ('__dict__', {'_FuncPtr': <class
'ctypes._FuncPtr'>, '_handle': 1690304512, '_name':
'd:/test_pytest/test_sensor_report/event_report.so'}),
('__doc__', "An instance of this class represents a loaded
dll/shared\n library, exporting functions using the standard C
calling\n convention (named 'cdecl' on Windows).\n\n The
exported functions can be accessed as attributes, or by\n
indexing with the function name. Examples:\n\n <obj>.qsort ->
callable object\n <obj>['qsort'] -> callable object\n\n
Calling the functions releases the Python GIL during the call
and\n reacquires it afterwards.\n "), ('__format__',
<built-in method __format__ of CDLL object at 0xffa87eec>),
('__getattr__', <bound method CDLL.__getattr__ of <CDLL
'd:/test_pytest/test_sensor_report/event_report.so', handle
64c00000 at ffa87eec>>), ('__getattribute__', <method-wrapper
'__getattribute__' of CDLL object at 0xffa87eec>),
('__getitem__', <bound method CDLL.__getitem__ of <CDLL
'd:/test_pytest/test_sensor_report/event_report.so', handle
64c00000 at ffa87eec>>), ('__hash__', <method-wrapper
'__hash__' of CDLL object at 0xffa87eec>), ('__init__',
<bound method CDLL.__init__ of <CDLL
'd:/test_pytest/test_sensor_report/event_report.so',
handle 64c00000 at ffa87eec>>), ('__module__', 'ctypes'),
('__new__', <built-in method __new__ of type object at
0x3d35b600>), ('__reduce__', <built-in method __reduce__ of
CDLL object at 0xffa87eec>), ('__reduce_ex__', <built-in
method __reduce_ex__ of CDLL object at 0xffa87eec>),
('__repr__', <bound method CDLL.__repr__ of <CDLL
'd:/test_pytest/test_sensor_report/event_report.so',
handle 64c00000 at ffa87eec>>), ('__setattr__',
<method-wrapper '__setattr__' of CDLL object at
0xffa87eec>), ('__sizeof__', <built-in method
__sizeof__ of CDLL object at 0xffa87eec>),
('__str__', <method-wrapper '__str__' of CDLL object
at 0xffa87eec>), ('__subclasshook__', <built-in
method __subclasshook__ of type object at
0xffae8204>), ('__weakref__', None),
('_func_flags_', 1), ('_func_restype_', <class
'ctypes.c_long'>), ('_handle', 1690304512),
('_name',
'd:/test_pytest/test_sensor_report/event_report.so')]
If you mock it you pretend it is reliable. Or at least do not test mocked functionality in the test using the mock.
No point in mocking exactly C function, no need in loading SO object.
Mock self.event and add Mock instance "read_sensor" to it, use the mock.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With