如何对移动操作进行单元测试(默认)?
How do I unit test (default) move operations?
当我尝试为仅移动类编写单元测试时,我遇到了这个问题。我不知道如何编写一个测试来检查移动操作是否真的移动了类的数据成员。我在这里包含一个简化的类示例,该示例与我正在处理的内容相似。实际上,该类支持更多的操作和(std::multimap
(数据成员,这些操作和((数据成员在这里不应该相关。
#include <vector>
class MyClass {
public:
inline MyClass() = default;
MyClass(const MyClass& other) = delete;
MyClass(MyClass&& other) = default;
MyClass& operator=(const MyClass& other) = delete;
MyClass& operator=(MyClass&& other) = default;
~MyClass() = default;
inline void set(const std::vector<MyStruct>& data) {data_ = data;}
inline const std::vector<MyStruct>& get() {return data_;}
private:
std::vector<MyStruct> data_;
};
MyStruct
只包含基元数据类型(int
、float
和double
(和一些std::string
类型作为(public
(数据成员。为了完整起见,我在末尾添加了MyStruct
的定义。
我什至不确定如何开始,也无法通过在线搜索找到任何东西。理想情况下,googletest 或 googlemock 解决方案会很棒,但只是一种通用方法或在其他测试框架工作中如何完成它可能会帮助我理解它并在我首选的框架中实现它。
#include <string>
struct MyStruct {
int foo;
float bar;
double baz;
std::string fips;
};
到目前为止的解决方案(来自下面的评论和答案(:
可能的办法1
根据我与@MutableSideEffect的交流
模拟数据成员并测试在调用MyClass
的移动操作时是否调用其移动操作。
这似乎简单明了。这指示 (MyClass
default
ed( 的 ( ed( 移动操作是否使用了每个数据成员的移动操作。数据成员的类型应负责提供适当的移动操作。
我唯一的问题是,如果不对整个代码进行模板化,我不知道如何模拟我无法访问其实现的数据类型(如用于模拟非虚拟函数的谷歌模拟文档中所述(。
不过,在这种特殊情况下,我仍然可以模拟MyStruct
并测试在调用MyClass
的移动操作时是否调用其移动操作。
可能的办法2
基于@Eljay的回答。
将一个数据成员(例如Marker mark
(添加到我定义的每个类中,或者添加到我想知道在调用类的移动操作时是否移动其数据成员的每个类。指示Marker
类在内部状态中记录其构造函数的哪些构造函数导致其构造。然后测试MyClass
的移动操作是否会导致其数据成员的内部状态mark
反映它已被移动。
我不确定这种方法如何充分测试所有数据成员,而不仅仅是mark
数据成员。此外,这让我想起了很多只是嘲笑数据成员,这可以追溯到方法 1。
这是一种使用 Marker 成员变量跟踪对象状态的方法。 请记住,std::move
并不意味着对象将被移动,它只会使对象有资格被移动。
一旦对象被移出,它就处于"有效但未指定的状态",适合被销毁或重新分配。 (一些标准C++库类型在从中移出后对状态的保证稍强一些,例如std::vector
和std::unique_ptr
。
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <cassert>
#ifndef TESTING
#define TESTING 1
#endif
namespace {
struct Marker final {
char const* state;
~Marker() { state = "destructed"; }
Marker() : state{"constructed"} {}
Marker(Marker const&) noexcept : state{"copy constructed"} {}
Marker(Marker&& other) noexcept : state{"move constructed"} { other.state = "move constructed husk"; }
Marker& operator=(Marker const&) noexcept { state = "assigned"; return *this; }
Marker& operator=(Marker&& other) noexcept { state = "move assigned"; other.state = "move assigned husk"; return *this; }
void print(std::ostream&) const;
};
void Marker::print(std::ostream& out) const {
out << state;
}
std::ostream& operator<<(std::ostream& out, Marker const& marker) {
marker.print(out);
return out;
}
void test();
class BigFancyClass {
friend void test();
std::vector<std::string> v;
public:
BigFancyClass() = default;
BigFancyClass(BigFancyClass const&) = default;
BigFancyClass(BigFancyClass&&) = default;
BigFancyClass& operator=(BigFancyClass const&) = default;
BigFancyClass& operator=(BigFancyClass&&) = default;
#if TESTING
Marker mark;
#endif
};
void test() {
std::cout << "Running test()... ";
BigFancyClass bfc;
bfc.v.push_back("hello");
bfc.v.push_back("world");
assert(bfc.v.size() == 2);
assert(std::strcmp(bfc.mark.state, "constructed") == 0);
BigFancyClass bfc2 = std::move(bfc);
assert(bfc.v.size() == 0);
assert(bfc2.v.size() == 2);
assert(std::strcmp(bfc.mark.state, "move constructed husk") == 0);
assert(std::strcmp(bfc2.mark.state, "move constructed") == 0);
BigFancyClass bfc3;
bfc3 = std::move(bfc2);
assert(std::strcmp(bfc2.mark.state, "move assigned husk") == 0);
assert(std::strcmp(bfc3.mark.state, "move assigned") == 0);
std::cout << "DONEn";
}
} // anon
int main() {
test();
}
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- 在子目录中使用target_sources()命令时用于单元测试(qtest)的项目结构
- VC++本机单元测试,找不到调试符号
- 用于交叉编译和CMake的预处理器宏的单元测试
- C++ 用于单元测试的模板模板
- 提升 1.64 单元测试编译失败
- 单元测试欧拉到四元数实现失败
- 运行 C++ 单元测试时LNK2005链接错误
- 禁用自动捕获 Googletest 单元测试中的C++异常
- 有没有办法在不使用 #ifdef 的情况下不编译发布版本中的单元测试函数体?
- 使用 Google Test 对自定义断言函数进行单元测试
- 如何将我的 CMake 项目配置为运行所有单元测试?
- 在Qt C++单元测试中动态加载QQuickWindow而不是QQuickWidget
- MS 本机单元测试 - 断言::线程失败不起作用
- 如何获取 CMake 单元测试的相对路径?
- QTimer 超时不会在单元测试中触发
- 如何在提升构建中设置环境变量以进行提升单元测试框架?
- 在 AtMega32a 上运行的C++的单元测试
- 使用 gtest 框架在单元测试代码中检查目标对象的私有变量的最佳实践是什么?
- 如何对移动操作进行单元测试(默认)?