我是cpp的新手。如果不在Foo中调用任何东西,我如何在clazz中单独测试条?
clazz.h
class Clazz {
public:
void bar (); //its implementation will call Foo::foo ()
}
myfile.cc
namespace Foo {
void foo () { /* do something */ }
}
答案 0 :(得分:2)
像Caramiriel建议的那样,你的班级Clazz
可以接受一个指向func foo
的指针,你可以用它代替另一个虚拟函数进行单元测试。
class Clazz
{
public:
typedef void (*fooFunc)();
Clazz(fooFunc foo) : m_fooFunc(foo) {}
void bar (); //its implementation will call Foo::foo ()
private:
fooFunc m_fooFunc;
};
namespace Foo
{
void foo () { /* do something */ }
}
void dummy() { }
Clazz a(Foo::foo);
Clazz b(dummy);
答案 1 :(得分:2)
免责声明我在Typemock工作。
有一种方法可以在不创建包装器或将方法更改为虚拟,或添加间接逻辑或传递函数指针的情况下对此进行测试。
//Use Isolator++ to fake foo.
WHEN_CALLED( Foo::foo() ).Ignore();
这是使用Typemock Isolator++。这是完整的代码:
namespace Foo
{
void foo () { throw "error"; } /* we want to fake this implementation */
}
class Clazz
{
public:
void bar () //its implementation will call Foo::foo ()
{
Foo::foo();
}
};
TEST_F(FakeStaticMethods, DontFailWhenBarIsCalled)
{
WHEN_CALLED( Foo::foo() ).Ignore();
Clazz c;
c.bar(); // WOW! code will not fail, no changes to production code
}
答案 2 :(得分:0)
只要事先对foo()
进行了适当的单元测试,我就不会在Clazz
的单元测试中看到使用它的固有问题。或者你也会发布一个STL算法?
如果您担心自己,那么在没有Clazz
的情况下无法对foo()
进行单元测试,那么这表明您的代码没有充分模块化,例如使用函数指针,模板或std::function
来改变它。
如果您仍想在不Clazz
的情况下测试foo()
并且不更改Clazz::bar()
的结构/界面,则可以执行以下操作之一(或多或少难看且出错)容易的事情:
3.1在班级内使用#if
s
3.2将使用指令从using Foo
更改为using FooMock
3.3有一个单独的构建配置,你不能编译Foo.cpp
而是编译FooMock.cpp
(你需要一个单独的配置来测试foo()
)
答案 3 :(得分:0)
您有两种解决方案:
Clazz
。这样可以很容易地拦截函数调用,并防止它发生。Foo::foo
的实现中链接,而是提供虚拟实现/模拟。让我们来看看你的可能性。
你需要编写一个提供全局函数功能的包装器。让我们使用一个接口并实现它:
class AbstractFooWrapper {
public:
virtual void foo() = 0;
};
class FooWrapper : public AbstractFooWrapper {
public:
void foo() override {
Foo::foo();
}
};
class FakeFooWrapper : public AbstractFooWrapper {
public:
void foo() override { }
};
我们还需要更改Clazz
以使用包装器:
#include <memory>
class Clazz {
public:
Clazz(std::unique_ptr<AbstractFooWrapper> foo) : foo_(foo) { }
void bar(); // will call foo_.foo()
private:
std::unique_ptr<AbstractFooWrapper> foo_;
};
这样您就可以通过简单地为它分配Clazz
来测试FakeFooWrapper
;
Clazz c(std::unique_ptr<AbstractFooWrapper>(new FakeFooWrapper));
c.bar();
这将使您的代码更容易测试并且更易于组合。
但是,如果您想在代码中尽可能少地更改,请查看方法2。
将Foo::foo
的实现分成另一个文件,我们称之为foo.cpp
。这样你有两个文件
<强> foo.h中强>:
namespace Foo {
void foo();
}
<强> Foo.cpp中强>
#include "foo.h"
void Foo::foo() {
// do something that you dont want to do during testing
}
现在我们创建第三个虚假实现:
<强> fake_foo.cpp 强>
#include "foo.h"
void Foo::foo() {
return;
}
然后,您通常会为Clazz
编写测试,但是会链接到fake_foo.o
。
g++ test_clazz.cpp clazz.cpp fake_foo.cpp -o test_clazz
这样就不会调用真实的Foo::foo
。
一旦将定义与声明分开,您甚至不必编写单独的实现,您可以使用您选择的模拟框架。在turtle(适用于加速测试),这很容易做到。
#include <turtle/mock.hpp>
namespace Foo {
MOCK_FUNCTION( foo, 0, void(void) ); // name, arity, signature
}
TEST_CASE( clazz_bar_test ) // call your testing frameworks macro
{
Clazz c;
MOCK_EXPECT( Foo::foo ).once();
CHECK( c.bar() ); // whatever it is you want to test
}