模拟免费功能 [英] Mocking free function

查看:38
本文介绍了模拟免费功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,似乎找不到解决方案.

我使用 VS2005 SP1 编译代码.

我有一个全局函数:

A* foo();

我有一个模拟课

class MockA : public A {民众:MOCK_METHOD0 (bar, bool());...};

在源代码中,它是这样访问的:foo()->bar().我找不到嘲笑这种行为的方法.而且我不能改变来源,所以谷歌模拟烹饪书中的解决方案是不可能的.

任何正确方向的帮助或指示将不胜感激.:)

解决方案

不,这是不可能的,不改变源代码,或者带上你自己的与可执行代码链接的 foo() 版本.


来自 GoogleMock 的常见问题解答它说

<块引用>

我的代码调用了一个静态/全局函数.我可以嘲笑它吗?

你可以,但你需要做一些改变.

一般来说,如果您发现自己需要模拟一个静态函数,则表明您的模块耦合过于紧密(灵活性较差、可重用性较差、可测试性较差等).您可能最好定义一个小接口并通过该接口调用该函数,然后可以轻松模拟.最初需要一些工作,但通常很快就会收回成本.

这篇 Google 测试博客 post 说得很好.看看吧.

同样来自食谱

<块引用>

模拟免费功能

可以使用 Google Mock 来模拟自由函数(即 C 风格的函数或静态方法).您只需要重写代码即可使用接口(抽象类).

不是直接调用自由函数(比如 OpenFile),而是为它引入一个接口并有一个调用自由函数的具体子类:

class FileInterface {

 公开:...virtual bool Open(const char* path, const char* mode) = 0;};

<块引用>

class File : public FileInterface {

 公开:...virtual bool Open(const char* path, const char* mode) {返回 OpenFile(路径,模式);}};

<块引用>

您的代码应该与 FileInterface 对话以打开文件.现在可以轻松模拟该函数.

这可能看起来很麻烦,但在实践中,您通常可以将多个相关函数放在同一个界面中,因此每个函数的语法开销会低得多.

如果您担心虚函数产生的性能开销,并且分析证实了您的担忧,您可以将其与模拟非虚方法的秘诀结合起来.


正如您在评论中提到的,您实际上提供了自己的 foo() 版本,您可以使用另一个模拟类的全局实例轻松解决这个问题:

struct IFoo {虚拟 A* foo() = 0;虚拟 ~IFoo() {}};结构 FooMock : 公共 IFoo {FooMock() {}虚拟 ~FooMock() {}MOCK_METHOD0(foo, A*());};FooMock fooMock;//你的 foo() 实现A* foo() {返回 fooMock.foo();}测试(...) {EXPECT_CALL(fooMock,foo()).时代(1).WillOnceReturn(new MockA());//...}

不要忘记在每个测试用例运行后清除所有调用预期.

I am stuck in a problem and can't seem to find the solution.

I am using VS2005 SP1 for compiling the code.

I have a global function:

A* foo();

I have a mock class

class MockA : public A {
public:
    MOCK_METHOD0 (bar, bool());
    ...
};

In the sources, it is accessed like this: foo()->bar(). I cannot find a way to mock this behavior. And I cannot change the sources, so the solution in google mock cook book is out of question.

Any help or pointers in the right direction will be highly appreciated. :)

解决方案

No it's not possible, without changing the sources, or bringing your own version of foo() that is linked with the executable code.


From GoogleMock's FAQ it says

My code calls a static/global function. Can I mock it?

You can, but you need to make some changes.

In general, if you find yourself needing to mock a static function, it's a sign that your modules are too tightly coupled (and less flexible, less reusable, less testable, etc). You are probably better off defining a small interface and call the function through that interface, which then can be easily mocked. It's a bit of work initially, but usually pays for itself quickly.

This Google Testing Blog post says it excellently. Check it out.

Also from the Cookbook

Mocking Free Functions

It's possible to use Google Mock to mock a free function (i.e. a C-style function or a static method). You just need to rewrite your code to use an interface (abstract class).

Instead of calling a free function (say, OpenFile) directly, introduce an interface for it and have a concrete subclass that calls the free function:

class FileInterface {

 public:
  ...
  virtual bool Open(const char* path, const char* mode) = 0;
};

class File : public FileInterface {

 public:
  ...
  virtual bool Open(const char* path, const char* mode) {
    return OpenFile(path, mode);
  }
};

Your code should talk to FileInterface to open a file. Now it's easy to mock out the function.

This may seem much hassle, but in practice you often have multiple related functions that you can put in the same interface, so the per-function syntactic overhead will be much lower.

If you are concerned about the performance overhead incurred by virtual functions, and profiling confirms your concern, you can combine this with the recipe for mocking non-virtual methods.


As you mentioned in your comment that you actually provide your own version of foo(), you can easily solve this having a global instance of another mock class:

struct IFoo {
    virtual A* foo() = 0;
    virtual ~IFoo() {}
};

struct FooMock : public IFoo {
     FooMock() {}
     virtual ~FooMock() {}
     MOCK_METHOD0(foo, A*());
};

FooMock fooMock;

// Your foo() implementation
A* foo() {
    return fooMock.foo();
}

TEST(...) {
    EXPECT_CALL(fooMock,foo())
        .Times(1)
        .WillOnceReturn(new MockA());
    // ...
}

Don't forget to clear all call expectations, after each test case run.

这篇关于模拟免费功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆