简体   繁体   English

使用 CPP 文件中定义的函数测试模板类

[英]Testing templated classes with functions defined in CPP file

For a project that I am working on, I need to mock certain classes for testing to test different behaviours of functions.对于我正在进行的项目,我需要模拟某些类进行测试,以测试函数的不同行为。 For testing I use gtest.对于测试,我使用 gtest。 Because I am working on a game, the speed and efficiency of the code is of the essence.因为我在做一个游戏,所以代码的速度和效率是至关重要的。 Because of this requirement I do not want to mock my classes by using virtual functions, but I want to mock my classes with templates, so the implementation of the classes will be defined at compile time and I do not lose performance at run time.由于这个要求,我不想使用虚函数来模拟我的类,但我想用模板模拟我的类,所以类的实现将在编译时定义,我不会在运行时失去性能。 Furthermore, because I want to have the least amount of code bloat in my other header/source files I want to split my files into headers and source files, so that some of the includes can be set in the source file.此外,因为我希望在我的其他头文件/源文件中拥有最少的代码膨胀量,我想将我的文件拆分为头文件和源文件,以便可以在源文件中设置一些包含。 This approach however comes with a couple of problems.然而,这种方法有几个问题。

Because the templated functions are defined in a source file, there will need to be an explicit definition of the classes in the source file.因为模板函数是在源文件中定义的,所以需要在源文件中明确定义类。 Otherwise these templated functions will throw an 'undefined external symbol' error at compile time.否则,这些模板化函数将在编译时抛出“未定义的外部符号”错误。 This would not be a problem if I did not have two different projects, one for the game and one for testing, as I can't make an explicit definition of a mock in the test project.如果我没有两个不同的项目,一个用于游戏,一个用于测试,这将不是问题,因为我无法在测试项目中明确定义模拟。

I have tried a couple of solutions, but all of them have drawbacks.我尝试了几种解决方案,但它们都有缺点。 I will try to demonstrate what I have done with the following piece of code: (I know and use GMock, but this is an easier example)我将尝试用以下代码演示我所做的:(我知道并使用 GMock,但这是一个更简单的示例)

//Game project
//Foo.h
<template class Bar>
class Foo
{
public:
   Bar bar;
   bool ExampleFunction();
}

//Foo.cpp
#include "Foo.h"
<template class Bar>
bool Foo::ExampleFunction()
{
   return bar.Func() > 10;
}

//Testing project
//BarMock.h
class BarMock
{
public:
   int Func();
   int value;
}

//BarMock.cpp
#include "BarMock.h"
Bar::Func()
{
   return value;
}

//TestFoo.cpp
#include "Foo.h"
TEST(Tests, TestExample)
{
  Foo<BarMock> mocked;
  mocked.bar.value = 100;
  ASSERT_TRUE(mocked.ExampleFunction());
}

Solution 1: Include cpp file in testing project解决方案 1:在测试项目中包含 cpp 文件

This is already error prone, as including a cpp file is usually a no go. 这已经很容易出错,因为包含 cpp 文件通常是没有 go。 But if I only include the cpp file ONCE somewhere in the testing project it will not give me the 'c function already defined' error. 但是,如果我只在测试项目的某处包含一次 cpp 文件,它不会给我“c function 已定义”错误。 This in my opinion is not a solid solution (although it is the solution I am currently using), because if I do need a templated class in 2 locations of my testing project this will (almost) always give an error. 我认为这不是一个可靠的解决方案(尽管它是我目前使用的解决方案),因为如果我确实需要在我的测试项目的 2 个位置使用模板 class,这将(几乎)总是给出错误。
 //TestFoo.cpp #include "Foo.h" #include "Foo.cpp" // error prone, but does compile TEST(Tests, TestExample) { Foo<BarMock> mocked; mocked.bar.value = 100; ASSERT_TRUE(mocked.ExampleFunction()); }

Solution 2: Create definitions in header file解决方案 2:在 header 文件中创建定义

This is less error prone, but comes with some other drawbacks. 这不太容易出错,但也有其他一些缺点。 Like I have stated before I want to keep the bloat to a minimum, but with this solution I will also include all of the headers of the Foo header (say I need in Foo and include foo somewhere, then in somewhere I will also have ). 就像我之前说过的那样,我想将膨胀保持在最低限度,但是通过这个解决方案,我还将包括 Foo header 的所有标题(比如我需要在 Foo 中并在某个地方包含 foo,然后在某个地方我也会有) .
 //Game project //Foo.h <template class Bar> class Foo { public: Bar bar; bool ExampleFunction() { return bar.Func() > 10; } } //Foo.cpp removed

Solution 3: Create virtual functions for mocks解决方案 3:为模拟创建虚拟函数

This is my least favourite option, but it should be mentioned. 这是我最不喜欢的选项,但应该提及。 Like I have stated before, this comes with a runtime performance hit and I do not want to change most of my functions to virtual functions. 就像我之前所说的那样,这会影响运行时性能,我不想将我的大部分函数更改为虚拟函数。 But in this way you will not get errors. 但是这样你就不会出错。
 //BarMock.h class BarMock { public: int Func() override; int value; } //BarMock.cpp #include "BarMock.h" Bar::Func() override { return value; }

Which one of these options is the best?这些选项中哪一个是最好的? Is there any method that I have missed?有什么我错过的方法吗? I would love to hear someone's opinion about this as I could not find a 'good' solution online.我很想听听有人对此的看法,因为我在网上找不到“好的”解决方案。

A variation of solution #1 by renaming the files:通过重命名文件的解决方案#1的变体:

  • Foo.h Foo.h
#pragma once // or/and header guards
<template class Bar>
class Foo
{
public:
   Bar bar;
   bool ExampleFunction();
};
  • Foo.inl (or other extension.inc,.ixx,...) Foo.inl (或其他扩展名.inc,.ixx,...)
#pragma once // or/and header guards
#include "Foo.h"
template <class Bar>
bool Foo<Bar>::ExampleFunction()
{
   return bar.Func() > 10;
}
  • Foo.cpp Foo.cpp
#include "Foo.h"
#include "Foo.inc"
#include "Bar.h"

// explicit instantiation
template <> struct Foo<Bar>;
  • FooTest.cpp FooTest.cpp
#include "Foo.h"
#include "Foo.inc"
#include "BarMock.h"

// Testing code...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 模板化类中的模板化函数 - Templated functions in templated classes 为什么在实现头文件中定义的模板化函数和类时使用“tpp”文件? - Why use a “tpp” file when implementing templated functions and classes defined in a header? 模板化类中模板化函数的困难 - Difficulties with templated functions in templated classes 标头/ cpp文件中定义的功能的行为不同 - Functions defined in header / cpp file behaves different 快速傅立叶变换:即使标题和.cpp文件匹配,也使用模板化派生类“未定义引用”错误 - Fast Fourier Transform: using templated derived classes 'undefined reference' error even though header and .cpp file match 没有内联函数的没有.cpp文件的c ++类? - c++ classes without .cpp file without inline functions? 编译器如何处理cpp文件中定义的内联函数 - how the compiler processes inline functions defined in cpp file 现代C ++编译器是否可以内联cpp文件中定义的函数 - Can modern C++ compilers inline functions that are defined in a cpp file 如何检测.h文件是否包含.cpp文件中未定义的函数? - How to detect if .h files contains functions that arent defined in .cpp file? 测试使用协作者和模板化方法的类 - Testing Classes that Use Collaborators with Templated Methods
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM