, - .
, , / , 3 .
, std::this_thread, sleep_for(std::milliseconds).
0 -
, :
class untestable_class
{
public:
void some_function()
{
if (must_sleep())
{
auto sleep_duration = std::chrono::milliseconds(1000);
std::this_thread::sleep_for(sleep_duration);
}
}
};
:
void use_untestable_class()
{
untestable_class instance;
instance.some_function();
}
- sleep_for, , some_function unit test, .
1 -
, . , - , /.
"" , :
struct system_thread_policy1
{
static void sleep_milliseconds(long milliseconds)
{
auto sleep_duration = std::chrono::milliseconds(milliseconds);
std::this_thread::sleep_for(sleep_duration);
}
};
"" , :
struct mock_thread_policy1
{
static size_t sleep_milliseconds_count;
static size_t sleep_milliseconds_arg1;
static void sleep_milliseconds_reset()
{
sleep_milliseconds_count = 0;
sleep_milliseconds_arg1 = 0;
}
static void sleep_milliseconds(size_t milliseconds)
{
sleep_milliseconds_count++;
sleep_milliseconds_arg1 = milliseconds;
}
};
__declspec(selectany) size_t mock_thread_policy1::sleep_milliseconds_count;
__declspec(selectany) size_t mock_thread_policy1::sleep_milliseconds_arg1;
, , sleep_milliseconds :
template <typename thread_policy>
class testable_class1
{
public:
void some_function()
{
if (must_sleep())
{
thread_policy::sleep_milliseconds(sleep_duration_milliseconds);
}
}
private:
enum { sleep_duration_milliseconds = 1000 };
};
testable_class1 "" :
void use_testable_class1()
{
testable_class1<system_thread_policy1> instance;
instance.some_function();
}
unit test, testable_class1 "mock" :
void test_testable_class1()
{
mock_thread_policy1::sleep_milliseconds_reset();
testable_class1<mock_thread_policy1> instance;
instance.some_function();
assert(mock_thread_policy1::sleep_milliseconds_count == 1);
assert(mock_thread_policy1::sleep_milliseconds_arg1 == 1000);
}
:
:
- .
- reset unit test, , .
- , , , .
2 -
"" , :
struct system_thread_policy2
{
void sleep_milliseconds(size_t milliseconds) const
{
auto sleep_duration = std::chrono::milliseconds(milliseconds);
std::this_thread::sleep_for(sleep_duration);
}
};
"" , :
struct mock_thread_policy2
{
mutable size_t sleep_milliseconds_count;
mutable size_t sleep_milliseconds_arg1;
mock_thread_policy2()
: sleep_milliseconds_count(0)
, sleep_milliseconds_arg1(0)
{
}
void sleep_milliseconds(size_t milliseconds) const
{
sleep_milliseconds_count++;
sleep_milliseconds_arg1 = milliseconds;
}
};
, , , , , sleep_milliseconds:
template <typename thread_policy>
class testable_class2
{
public:
testable_class2(const thread_policy& policy = thread_policy()) : m_thread_policy(policy) { }
void some_function() const
{
if (must_sleep())
{
m_thread_policy.sleep_milliseconds(sleep_duration_milliseconds);
}
}
private:
testable_class2(const testable_class2&);
testable_class2& operator=(const testable_class2&);
enum { sleep_duration_milliseconds = 1000 };
const thread_policy& m_thread_policy;
};
testable_class2 "" :
void use_testable_class2()
{
const testable_class2<system_thread_policy2> instance;
instance.some_function();
}
unit test, testable_class2 "mock" :
void test_testable_class2()
{
mock_thread_policy2 thread_policy;
const testable_class2<mock_thread_policy2> instance(thread_policy);
instance.some_function();
assert(thread_policy.sleep_milliseconds_count == 1);
assert(thread_policy.sleep_milliseconds_arg1 == 1000);
}
:
:
- .
- (
testable_class2) - , , goo .
3 -
, , / , , .
-, , "" :
class testable_class3
{
public:
void some_function()
{
if (must_sleep())
{
sleep_milliseconds(sleep_duration_milliseconds);
}
}
private:
virtual void sleep_milliseconds(size_t milliseconds)
{
auto sleep_duration = std::chrono::milliseconds(milliseconds);
std::this_thread::sleep_for(sleep_duration);
}
enum { sleep_duration_milliseconds = 1000 };
};
-, , "" ( ):
class mock_testable_class3 : public testable_class3
{
public:
size_t sleep_milliseconds_count;
size_t sleep_milliseconds_arg1;
mock_testable_class3()
: sleep_milliseconds_count(0)
, sleep_milliseconds_arg1(0)
{
}
private:
virtual void sleep_milliseconds(size_t milliseconds)
{
sleep_milliseconds_count++;
sleep_milliseconds_arg1 = milliseconds;
}
};
testable_class3 :
void use_testable_class3()
{
testable_class3 instance;
instance.some_function();
}
unit test, testable_class3 "mock" :
void test_testable_class3()
{
mock_testable_class3 mock_instance;
auto test_function = [](testable_class3& instance) { instance.some_function(); };
test_function(mock_instance);
assert(mock_instance.sleep_milliseconds_count == 1);
assert(mock_instance.sleep_milliseconds_arg1 == 1000);
}
:
- , , .
- "" ""
sleep_for. - mocks , , .
:
final (++ 11), , , , .- / .
Test Run
:
int _tmain(int argc, _TCHAR* argv[])
{
test_testable_class1();
test_testable_class2();
test_testable_class3();
return 0;
}
runnable - http://pastebin.com/0qJaQVcD