52

我听说有可能让 google-test TestCase 类朋友加入我的类,从而使测试能够访问我的私人/受保护成员。

如何做到这一点?

4

4 回答 4

52

试试这个(直接来自谷歌测试文档......):

FRIEND_TEST(TestCaseName, TestName);

例如:

// foo.h
#include <gtest/gtest_prod.h>

// Defines FRIEND_TEST.
class Foo {
  ...
 private:
  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
  int Bar(void* x);
};

// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
  Foo foo;
  EXPECT_EQ(0, foo.Bar(NULL));
  // Uses Foo's private member Bar().
}
于 2010-03-07T13:38:10.393 回答
36

我知道这很旧,但我今天正在寻找相同的答案。“ gtest_prod.h ”只是引入了一个简单的宏来引用测试类。

#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test

所以FRIEND_TEST(FooTest, BarReturnsZeroOnNull);相当于:

friend class FooTest_BarReturnsZeroOnNull_Test;

这是有效的,因为每个测试都是它自己的类,如上一个答案中所述。

于 2012-10-08T16:18:58.643 回答
10

一个更好的策略是在你的单元测试中不允许友元测试。

Allowing friend tests accessing private members will lead to a code base that is hard to maintain. Tests that break whenever a component's inner implementation details are refactored is not what you want. If extra effort is instead put into getting a design where components can be tested through their public interface, you will get tests that only need updating whenever the public interface of a component is updated.

Tests relying on gtest/gtest_prod.h should be seen as a sign of poor design.

于 2017-04-18T17:30:51.500 回答
5

When your tested class and your test class are in a different namespace (e.g. your tests are in the global namespace), you may need to forward-declare your test class and add your namespace prefix in FRIEND_TEST:

// foo.h
#include <gtest/gtest_prod.h>

// forward-declaration of test class
class FooTest_BarReturnsZeroOnNull_Test; 

// Defines FRIEND_TEST.
class my_namespace::Foo {
    ...
private:
    // Specify the global namespace (`::`) in the `FRIEND_TEST()` usage
    FRIEND_TEST(::FooTest, BarReturnsZeroOnNull);
    int Bar(void* x);
};

// forward-declaration of this namespace from foo_test.cc
using namespace my_namespace;

...
TEST(FooTest, BarReturnsZeroOnNull) {
    Foo foo;
    EXPECT_EQ(0, foo.Bar(NULL));
    // Uses Foo's private member Bar().
}

I know that friend unit tests (or the friendliness in C++ in general) and white-box testing are a controversial subject, but when you work on complex, scientific algorithms, each step of which you need to test and validate, but that you don't want to expose in public (or even protected) interfaces, friend tests appear to me as a simple and pragmatic solution, especially in a test-driven development approach. It is always possible to refactor the code later (or to completely remove white-box tests) if it's against one's religion to use the friendliness or white-box testing.

于 2019-07-16T09:08:03.423 回答