当你写一个原型或者测试的时候,依赖整个object 是不可行和明智的。一个 mock object和 real object 有同样的接口(所以它可以像同一个使用),但是让你在运行时进行指定它应该如何被使用,它应当做什么(哪些方法应该被调用?以何种顺序?多少次?用什么参数?什么会被返回?)

注意:很容易弄混 fake objects 和 mock objects。实际上fakes 和 mocks意味着不同的事情在Test-Driven Development(TDD)社区:

Fake object(伪对象) 有 工作实现,但是经常采取一些捷径(也许让操作不昂贵),这会使它们不适合生产。内存中的文件系统就是一个例子。

Mocks 是有期望的预编程对象。由一些预期会被调用的 sepcification组成。

如果这对你来说太抽象的话,don't worry- 你需要记住最重要的就是mock 允许你使用它与你的代码进行交互。当你使用mocks的时候,你对于fakes和 mocks的区别就更清晰了,

Google C++ Mocking Framework (or Google Mock for short) 是一个用来创建 mock 类库(叫“框架”是因为这样听起来更cool),就像 java 的 jMock and EasyMock

使用 Google Mock 包含以下三个基本步骤:

1. 使用一些简单的macros 来描述 你想mock的接口,这将扩展你的mock 类。

2. 用很直观的语法来描述一些mock对象的期望和行为。

3. 练习使用mock 对象的 代码。任何 违反 expectation 的行为一出现就会被Google Mock 捕获。

Why Google Mock?

为什么使用 Google Mock

虽然Mock Object 可以帮助你移除测试中不必要的依赖,并使它们快速可靠,但是在C ++中手动使用mock是很难的:

      有些人不得不实现mocks。这个工作既乏味又容易出错。难怪有些人想要避免它。

      手动写的mock的质量是不可靠的,无法预测的。你可能看过一些真正抛光过的,但是你也许会看到一些被匆忙砍掉有各种零时限制的。

      你从一个mock 获得的知识不能使用到下一个mock上面。

相比之下,Java和Python程序员有一些精细的模拟框架,自动创建mock。因此,Mock是一种被证明是有效的技术,并在这些社区广泛采用的做法。拥有正确的工具绝对有所不同。

Google Mock旨在帮助C ++程序员。它的灵感来自jMock和EasyMock,但是设计时考虑了C ++的细节。它会帮助你的,如果你遇到以下问题:

         你被不怎么好的设计所困扰,早知道应该做更多的原型设计的,但一切都太迟了,但是用C++进行原型设计速度会很慢。

          您的测试很慢,因为它们依赖于太多的库或使用昂贵的资源(例如数据库)

           你的测试是脆弱的,因为他们使用的一些资源是不可靠的(例如网络)

           您想要测试代码如何处理失败(例如,文件校验和错误),但是不容易去制造这么一个失败。

           你想确保你的当前模块和其他模块的交互是正确的,但是观察交互是很不容易的;因此你诉诸于观察行动结束时的副作用,这是最尴尬的

           你想 mock out 你的 依赖,除了还mock还没有被实现;坦白的讲,你对那些手写的mock 不感冒

我们鼓励你像这样使用Google Mock:

         一个设计工具,它可以让你早日经常尝试你的接口设计。更多的迭代导致更好的设计!

          一个测试工具,切断所有测试的外部依赖,探测你的模块和其他模块的交互!

Getting Started

开始吧

使用Google Mock很容易! 在你的C ++源文件中,只要#include“gtest / gtest.h”和“gmock / gmock.h”,你已经准备好了。

A Case for Mock Turtles

让我们来看一个例子。假设你在开发一个图形程序依赖一个 LOGO-like的 API 来绘图。你该怎样测试它做了正确的事情呢?你可以运行它并且与一个golden screen snapshot进行比较,但是我承认:像这样测试是昂贵的并且很脆弱(如果你要更新到一个全新抗锯齿的图像该怎么办?你要更新你所有的golden images),如果你的所有测试都是这样的,这就很痛苦了。Fortunately,你学习到了Dependency Injection并且知道该作什么:不要让你的application 直接 调用 drawing API, 把API包在一个接口里(say, Turtle) and code to that interface:

class Turtle {
...
virtual ~Turtle() {}
virtual void PenUp() = ;
virtual void PenDown() = ;
virtual void Forward(int distance) = ;
virtual void Turn(int degrees) = ;
virtual void GoTo(int x, int y) = ;
virtual int GetX() const = ;
virtual int GetY() const = ;
};

(注意,Turtle的析构函数必须是虚拟的,就像你打算继承的所有类的情况一样 - 否则当通过基类指针删除一个对象时,派生类的析构函数不会被调用,你会得到损坏的程序状态,如内存泄漏。)

您可以控制 使用PenUp()和PenDown()控制turtle的运动是否留下轨迹,并通过 Forward(),Turn()和GoTo()控制其运动。最后,GetX()和GetY()告诉你当前位置的turtle。

你的程序通常正常使用这个接口的实际实现。在测试中,你可以使用 实现的Mock来替换。这让你很容易的检查你程序你调用的 drawing primitives。传了哪些参数,以什么样的顺序。以这种方式编写的测试更强大,更容易读取和维护(测试的意图表示在代码中,而不是在一些二进制图像中)运行得多,快得多。

Writing the Mock Class

如果你幸运,你需要使用的mock已经被一些好的人实现。但是,你发现自己在写一个模拟class,放松- Google Mock将这个任务变成一个有趣的游戏!

How to Define It

使用Turtle接口作为示例,以下是您需要遵循的简单步骤:

1. MockTurtle继承Turtle类

2.使用Turtle的虚函数(虽然可以使用模板来模拟非虚方法 mock non-virtual methods using templates,但是它更多的涉及)。计算它有多少参数。

3. 在 public 区: section of the child class, write MOCK_METHODn(); (or MOCK_CONST_METHODn(); if you are mocking a const method), where n is the number of the arguments; if you counted wrong, shame on you, and a compiler error will tell you so.

4. 现在来到有趣的部分:你采取函数签名,剪切和粘贴函数名作为宏的第一个参数,留下的作为第二个参数(如果你好奇,这是类型的功能)

5. 重复,直到您要模拟的所有虚拟功能完成。

After the process, you should have something like:

#include "gmock/gmock.h"  // Brings in Google Mock.
class MockTurtle : public Turtle {
public:
...
MOCK_METHOD0(PenUp, void());
MOCK_METHOD0(PenDown, void());
MOCK_METHOD1(Forward, void(int distance));
MOCK_METHOD1(Turn, void(int degrees));
MOCK_METHOD2(GoTo, void(int x, int y));
MOCK_CONST_METHOD0(GetX, int());
MOCK_CONST_METHOD0(GetY, int());
};

您不需要在其他地方定义这些模拟方法 - MOCK_METHOD *宏将为您生成定义。 就是这么简单!

一旦你掌握了它,你可以快速的写出 mock class,以至于你的 source control system 都不能处理你的check-in 了

Tips: 如果 这对你来说工作量太大了,你可以在 Google Mock 的 scripts/generator/目录下面找到gmock_gen.py 工具。

Command-line 工具需要python2.4 安装。你只要给它一个 定义了抽象类的C++文件,它就会给你打印 其mock class。由于C++语言的复杂性,这个脚本可能不总是工作正常,但确实很有用,read the user documentation.

Where to Put It

当你定义了 mock class,你得决定你把这些定义放到什么地方。有些人把它放在一个* _test.cc。当这些 mock对象是被一个人或者一个团队使用的时候,这样定义就很好。否则,当Foo的所有者改变它,你的测试可能会中断。 (你不能真正期望Foo的维护者修复使用Foo的每个测试,你能吗?)

所以,经验法则是:如果你需要模拟Foo并且它由其他人拥有,在Foo的包中定义模拟类(更好的是,在一个测试子包中,你可以清楚地分离生产代码和测试实用程序),并且把它放在mock_foo.h。然后每个人都可以从它们的测试引用mock_foo.h。如果Foo变化,只有一个MockFoo的副本要更改,只有依赖于更改的方法的测试需要修复。

另外一种方法:你可以在Foo的顶部引入一个 薄层FooAdaptor ,并将代码引入这一新的接口。因为你拥有FooAdaptor,你可以更容易的吸收Foo的变化。虽然这是最初的工作,仔细选择适配器接口可以使您的代码更容易编写和更加可读性,因为你可以选择FooAdaptor适合你的特定领域比Foo更好。

Using Mocks in Tests

一旦你有了Mock 类,使用它非常容易。典型的工作流程如下:

1. 从测试命名空间导入Google Mock名称,以便您可以使用它们(每个文件只需执行一次。请记住,命名空间是一个好主意,有利于您的健康。)

2. 创建一些 mock对象

3.指定你对它们的期望(一个方法被调用多少次?有什么参数?它应该做什么等等)。

4.练习一些使用mock的代码; 可以使用Google Test断言检查结果。如果一个mock方法被调用超过预期或错误的参数,你会立即得到一个错误。

5. 当模mock destructed,Google Mock将自动检查是否满足了对其的所有期望

例子:

#include "path/to/mock-turtle.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using ::testing::AtLeast; // #1 TEST(PainterTest, CanDrawSomething) {
MockTurtle turtle; // #2
EXPECT_CALL(turtle, PenDown()) // #3
.Times(AtLeast()); Painter painter(&turtle); // #4 EXPECT_TRUE(painter.DrawCircle(, , ));
} // #5 int main(int argc, char** argv) {
// The following line must be executed to initialize Google Mock
// (and Google Test) before running the tests.
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}

正如你可能已经猜到的,这个测试检查PenDown()被调用至少一次。 如果painter对象没有调用此方法,您的测试将失败,并显示如下消息:

path/to/my_test.cc:: Failure
Actual function call count doesn't match this expectation:
Actually: never called;
Expected: called at least once.

提示1:如果从Emacs缓冲区运行测试,您可以在错误消息中显示的行号上按<Enter>,直接跳到失败的预期。

提示2:如果你的mock object 从来没有被删除,最终的验证不会发生。因此,当您在堆上分配mock时,在测试中使用堆泄漏检查器是个好主意。

重要提示:Google Mock 需要expectation 在mock 函数被调用之前就设置,否者 行为就是 未定义的(undefined)。尤其是,你不能交错 EXPECT_CALL()和调用函数

这意味着EXPECT_CALL()应该被读取为期望call将在未来发生,而不是call已经发生。为什么Google Mock会这样工作?

好的,事先指定期望允许Google Mock在上下文(堆栈跟踪等)仍然可用时立即报告违例。这使得调试更容易。

诚然,这个测试是设计的,没有做太多。不使用Google Mock,您也可以轻松实现相同的效果。然而,正如我们将很快揭示的,Google Mock允许你做更多的。

Using Google Mock with Any Testing Framework

如果您要使用除Google测试(例如CppUnit或CxxTest)之外的其他测试框架作为测试框架,只需将上一节中的main()函数更改为:

int main(int argc, char** argv) {
// The following line causes Google Mock to throw an exception on failure,
// which will be interpreted by your testing framework as a test failure.
::testing::GTEST_FLAG(throw_on_failure) = true;
::testing::InitGoogleMock(&argc, argv);
... whatever your testing framework requires ...
}

这种方法有一个catch:它有时使Google Mock从一个模拟对象的析构器中抛出异常。对于某些编译器,这有时会导致测试程序崩溃。 你仍然可以注意到测试失败了,但它不是一个优雅的失败。

更好的解决方案是使用Google Test的事件侦听器APIevent listener API 来正确地向测试框架报告测试失败。 您需要实现事件侦听器接口的OnTestPartResult()方法,但它应该是直接的。

如果这证明是太多的工作,我们建议您坚持使用Google测试,它与Google Mock无缝地工作(实际上,它在技术上是Google Mock的一部分)。 如果您有某个原因无法使用Google测试,请告诉我们。

Setting Expectations

成功使用Mock Object的关键是对它设置正确的期望。 如果你设置的期望太严格,你的测试将失败作为无关的更改的结果。 如果你把它们设置得太松,错误可以通过。 你想做的只是正确的,使你的测试可以捕获到你想要捕获的那种错误。 Google Mock为您提供了必要的方法“恰到好处”。

General Syntax

在 Google Mock 中我们在 mock mecthod 中使用 EXPECT_CALL() 宏去设置expectation。 一般的语法是:

EXPECT_CALL(mock_object, method(matchers))
.Times(cardinality)
.WillOnce(action)
.WillRepeatedly(action);

宏有两个参数:首先是mock对象,然后是方法及其参数。 请注意,两者之间用逗号(,)分隔,而不是句点(.)。 (为什么要使用逗号?答案是,这是必要的技术原因。)

宏之后可以是一些可选的子句,提供有关期望的更多信息。 我们将在下面的章节中讨论每个子句是如何工作的。

此语法旨在使期望读取如英语。 例如,你可能猜到

using ::testing::Return;
...
EXPECT_CALL(turtle, GetX())
.Times()
.WillOnce(Return())
.WillOnce(Return())
.WillRepeatedly(Return());

turtle对象的GetX()方法将被调用五次,它将第一次返回100,第二次返回150,然后每次返回200。 有些人喜欢将这种语法风格称为域特定语言(DSL)。

注意:为什么我们使用宏来做到这一点? 它有两个目的:第一,它使预期容易识别(通过grep或由人类读者),其次它允许Google Mock在消息中包括失败的期望的源文件位置,使调试更容易。

Matchers: What Arguments Do We Expect?

当一个mock函数接受参数时,我们必须指定我们期望什么参数; 例如:

// Expects the turtle to move forward by 100 units.
EXPECT_CALL(turtle, Forward());

有些时候你也许不想要太具体(记住,谈论测试太僵硬,超过规范导致脆弱的测试和模糊测试的意图,因此,我们鼓励你只指定必要的 -不多也不少 ),如果你只关心 Forward() 会被调用,但是对 具体的参数不感兴趣,写_ 作为 参数,这意味“什么都可以”:

using ::testing::_;
...
// Expects the turtle to move forward.
EXPECT_CALL(turtle, Forward(_));

_是我们称为匹配器的实例.匹配器就像一个谓词,可以测试一个参数是否是我们期望的.你可以在EXPECT_CALL()里面使用一个匹配器来替换某一个参数。内置匹配器的列表可以在CheatSheet中找到。 例如,这里是Ge(大于或等于)匹配器:

using ::testing::Ge;
...
EXPECT_CALL(turtle, Forward(Ge()));

这检查,turtle将被告知前进至少100单位。

Cardinalities: How Many Times Will It Be Called?

我们可以在EXPECT_CALL()之后指定的第一个子句是Times()。我们把它的参数称为基数,因为它告诉调用应该发生多少次。它允许我们重复一个期望多次,而不实际写多次。更重要的是,一个基数可以是“模糊的”,就像一个匹配器。这允许用户准确地表达测试的意图。

一个有趣的特殊情况是当我们说Times(0)。你可能已经猜到了 - 这意味着函数不应该使用给定的参数,而且Google Mock会在函数被(错误地)调用时报告一个Google测试失败。我们已经看到AtLeast(n)作为模糊基数的一个例子。有关您可以使用的内置基数列表,请参见CheatSheet

Times()子句可以省略。如果你省略Times(),Google Mock会推断出你的基数。规则很容易记住:

  • 如果WillOnce()和WillRepeatedly()都不在EXPECT_CALL()中,则推断的基数是Times(1)。
  • 如果有n个WillOnce(),但没有WillRepeatedly(),其中n> = 1,基数是Times(n)
  • 如果有n个WillOnce()和一个WillRepeatedly(),其中n> = 0,基数是Times(AtLeast(n))。

快速测验:如果一个函数期望被调用两次,但实际上调用了四次,你认为会发生什么?

Actions: What Should It Do?

记住,一个模拟对象实际上没有工作实现? 我们作为用户必须告诉它当一个方法被调用时该做什么。 这在Google Mock中很容易。

首先,如果一个模拟函数的返回类型是内置类型或指针,该函数有一个默认动作(一个void函数将返回,一个bool函数将返回false,其他函数将返回0)。

此外,在C ++ 11及以上版本中,返回类型为默认可构造(即具有默认构造函数)的模拟函数具有返回默认构造值的默认动作。 如果你不说什么,这个行为将被使用。

第二,如果模拟函数没有默认动作,或者默认动作不适合你,你可以使用一系列WillOnce()子句指定每次期望匹配时要采取的动作,后跟一个可选的WillRepeatedly ()。例如:

using ::testing::Return;
...
EXPECT_CALL(turtle, GetX())
.WillOnce(Return())
.WillOnce(Return())
.WillOnce(Return());

这说明turtle.GetX()将被调用三次(Google Mock从我们写的WillOnce()子句中推断出了这一点,因为我们没有明确写入Times()),并且会返回100,200, 和300。

using ::testing::Return;
...
EXPECT_CALL(turtle, GetY())
.WillOnce(Return())
.WillOnce(Return())
.WillRepeatedly(Return());

turtle.GetY()将被调用至少两次(Google Mock知道这一点,因为我们写了两个WillOnce()子句和一个WillRepeatedly(),没有明确的Times()),将第一次返回100,200 第二次,300从第三次开始。

当然,如果你明确写一个Times(),Google Mock不会试图推断cardinality(基数)本身。 如果您指定的数字大于WillOnce()子句,该怎么办? 好了,毕竟WillOnce()已用完,Google Mock每次都会为函数执行默认操作(除非你有WillRepeatedly()。)。

除了Return()之外,我们可以在WillOnce()中做什么? 您可以使用ReturnRef(variable)返回引用,或调用预定义函数等。

重要说明:EXPECT_CALL()语句只评估一次操作子句,即使操作可能执行多次。 因此,您必须小心副作用。 以下可能不会做你想要的:

int n = ;
EXPECT_CALL(turtle, GetX())
.Times()
.WillRepeatedly(Return(n++));

不是连续返回100,101,102,...,这个mock函数将总是返回100,因为n ++只被计算一次。 类似地,当执行EXPECT_CALL()时,Return(new Foo)将创建一个新的Foo对象,并且每次都返回相同的指针。 如果你想要每次都发生副作用,你需要定义一个自定义动作,我们将在 CookBook中教授。

另一个测验! 你认为以下是什么意思?

using ::testing::Return;
...
EXPECT_CALL(turtle, GetY())
.Times()
.WillOnce(Return());

显然turtle.GetY()被期望调用四次。但如果你认为它会每次返回100,三思而后行!请记住,每次调用函数时都将使用一个WillOnce()子句,然后执行默认操作。所以正确的答案是turtle.GetY()将第一次返回100,但从第二次返回0,因为返回0是int函数的默认操作

Using Multiple Expectations

到目前为止,我们只列出了你有一个期望的例子。更现实地,你要指定对多个模拟方法的期望,这可能来自多个模拟对象。

默认情况下,当调用模拟方法时,Google Mock将按照它们定义的相反顺序搜索期望值,并在找到与参数匹配的活动期望时停止(您可以将其视为“新规则覆盖旧的规则“)。如果匹配期望不能再接受任何调用,您将得到一个上限违反的失败。这里有一个例子:

using ::testing::_;
...
EXPECT_CALL(turtle, Forward(_)); // #1
EXPECT_CALL(turtle, Forward()) // #2
.Times();

如果Forward(10)在一行中被调用三次,第三次它将是一个错误,因为最后的匹配期望(#2)已经饱和。然而,如果第三个Forward(10)被Forward(20)替换,则它将是OK,因为现在#1将是匹配期望。

附注:Google Mock为什么要以与预期相反的顺序搜寻匹配?原因是,这允许用户在模拟对象的构造函数中设置默认期望,或测试夹具的设置阶段中设置默认期望,然后通过在测试体中写入更具体的期望来定制模拟。所以,如果你对同一个方法有两个期望,你想把一个具有更多的特定的匹配器放在另一个之后,或更具体的规则将被更为一般的规则所覆盖。

Ordered vs Unordered Calls

默认情况下,即使未满足较早的期望,期望也可以匹配调用。换句话说,调用不必按照期望被指定的顺序发生

有时,您可能希望所有预期的调用以严格的顺序发生。在Google Mock中说这很容易

using ::testing::InSequence;
...
TEST(FooTest, DrawsLineSegment) {
...
{
InSequence dummy; EXPECT_CALL(turtle, PenDown());
EXPECT_CALL(turtle, Forward());
EXPECT_CALL(turtle, PenUp());
}
Foo();
}

通过创建类型为InSequence的对象,其范围中的所有期望都被放入序列中,并且必须按顺序发生。因为我们只是依靠这个对象的构造函数和析构函数做实际的工作,它的名字真的无关紧要。

在这个例子中,我们测试Foo()按照书写的顺序调用三个期望函数。如果调用是无序的,它将是一个错误。

如果你关心一些呼叫的相对顺序,但不是所有的呼叫,你能指定一个任意的部分顺序吗?答案是...是的!如果你不耐烦,细节可以在CookBook中找到。)

All Expectations Are Sticky (Unless Said Otherwise)

所有期望都是粘滞的(Sticky)(除非另有说明)

现在,让我们做一个快速测验,看看你可以多好地使用这个模拟的东西。你会如何测试,turtle被要求去原点两次(你想忽略任何其他指令)?

在你提出了你的答案,看看我们的比较的笔记(自己先解决 - 不要欺骗!):

using ::testing::_;
...
EXPECT_CALL(turtle, GoTo(_, _)) // #1
.Times(AnyNumber());
EXPECT_CALL(turtle, GoTo(, )) // #2
.Times();

假设turtle.GoTo(0,0)被调用了三次。 第三次,Google Mock将看到参数匹配期望#2(记住,我们总是选择最后一个匹配期望)。 现在,由于我们说应该只有两个这样的调用,Google Mock会立即报告错误。 这基本上是我们在上面“使用多个期望”部分中告诉你的。

这个例子表明,Google Mock的期望在默认情况下是“粘性”,即使在我们达到其调用上界之后,它们仍然保持活动。 这是一个重要的规则要记住,因为它影响规范的意义,并且不同于它在许多其他Mock框架中做的(为什么我们这样做?因为我们认为我们的规则使常见的情况更容易表达和 理解。)。

简单? 让我们看看你是否真的理解它:下面的代码说什么?

using ::testing::Return;
...
for (int i = n; i > ; i--) {
EXPECT_CALL(turtle, GetX())
.WillOnce(Return(*i));
}

如果你认为它说,turtle.GetX()将被调用n次,并将返回10,20,30,...,连续,三思而后行! 问题是,正如我们所说,期望是粘性的。 所以,第二次turtle.GetX()被调用,最后(最新)EXPECT_CALL()语句将匹配,并将立即导致“上限超过(upper bound exceeded)”错误 - 这段代码不是很有用!

一个正确的说法是turtle.GetX()将返回10,20,30,...,是明确说,期望是不粘的。 换句话说,他们应该在饱和后尽快退休:

using ::testing::Return;
...
for (int i = n; i > ; i--) {
EXPECT_CALL(turtle, GetX())
.WillOnce(Return(*i))
.RetiresOnSaturation();
}

而且,有一个更好的方法:在这种情况下,我们期望调用发生在一个特定的顺序,我们排列动作来匹配顺序。 由于顺序在这里很重要,我们应该显示的使用一个顺序:

using ::testing::InSequence;
using ::testing::Return;
...
{
InSequence s; for (int i = ; i <= n; i++) {
EXPECT_CALL(turtle, GetX())
.WillOnce(Return(*i))
.RetiresOnSaturation();
}
}

Uninteresting Calls

模拟对象可能有很多方法,并不是所有的都是那么有趣。例如,在一些测试中,我们可能不关心GetX()和GetY()被调用多少次。

在Google Mock中,如果你对一个方法不感兴趣,只是不要说什么。如果调用此方法,您将在测试输出中看到一个警告,但它不会失败。

What Now?

恭喜!您已经学会了足够的Google Mock开始使用它。现在,您可能想要加入googlemock讨论组,并且实际上使用Google Mock编写一些测试 - 这很有趣。嘿,它甚至可以上瘾 - 你已经被警告。

然后,如果你想增加你的Mock商,你应该移动到 CookBook。您可以了解Google Mock的许多高级功能,并提高您的享受和测试幸福的水平。

GoogleTest 之路3-Mocking Framework的更多相关文章

  1. Googletest - Google Testing and Mocking Framework

    Googletest - Google Testing and Mocking Framework https://github.com/google/googletest

  2. Testing with a mocking framework (EF6 onwards)

    When writing tests for your application it is often desirable to avoid hitting the database.  Entity ...

  3. 什么是Mocking framework?它有什么用?

    原位地址:http://codetunnel.com/blog/post/what-is-a-mocking-framework-why-is-it-useful 今天我想讲下关于mocking fr ...

  4. Mocking framework

    [译] 什么是Mocking framework?它有什么用? 原位地址:http://codetunnel.com/blog/post/what-is-a-mocking-framework-why ...

  5. What is a mocking framework? Why is it useful?

    Today I want to talk about mocking frameworks and why they are useful. In order to do that I first n ...

  6. 什么是Mocking framework?它有什么用?(转)

    今天我想讲下关于mocking frameworks,并且解释下他为什么有用处.我将给你们展示用和不用mocking framework两种测试方法. 假设我们已经有了一个Driver类: publi ...

  7. GoogleTest 之路2-Googletest 入门(Primer)

    Why googletest? 为啥要用GoogleTest呢? googletest 是由测试技术Team 开发的带有google 特殊的需求和限制的测试框架. 不管你在什么平台上写C++代码,go ...

  8. <Android Framework 之路> N版本 Framework Camera的一些改动

    前言 Android N版本最近发布,Nougat是否好吃,不得而知,慢慢看下~ 感谢AndroidXref这个网站,给开发者提供了大量的便捷~以后学习Android就靠它了. N版本上Framewo ...

  9. GoogleTest 之路1-Generic Build Instructions编译指导总方案

    准备工作 为了在你的测试中使用GoogleTest, 你必须让你的编译系统 知道到哪里去寻找GoogleTest 的头文件和源文件. 具体的方法只能依赖于你具体使用的哪种编译系统了,一般来讲这个非常容 ...

随机推荐

  1. ssrf漏洞分析

    ssrf漏洞分析 关于ssrf 首先简单的说一下我理解的ssrf,大概就是服务器会响应用户的url请求,但是没有做好过滤和限制,导致可以攻击内网. ssrf常见漏洞代码 首先有三个常见的容易造成ssr ...

  2. NET高性能IO

    System.IO.Pipelines: .NET高性能IO https://www.cnblogs.com/xxfy1/p/9290235.html System.IO.Pipelines是一个新的 ...

  3. python 3 学习字符串和编码

    字符串和编码 阅读: 895464 字符编码 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字 ...

  4. 无线网路由器的dBm值

    首先,我们需要知道的是无线信号 dbm都是负数,最大是0:dbm值只在一种情况下为0,那就是在理想状态下经过实验测量的结果,一般我们认为 dbm为0是其最大值,意味着接收方把发射方发射的所有无线信号都 ...

  5. UIScrollView使用stoboard自动布局

    使用stoboard布局 scrollView 是有点麻烦的,首先我们往往约束好一个 scrollView 然后在添加子控件,此时都会报错,原因是, scrollView必须确定滚动范围 然后在使用V ...

  6. spring data jpa 简单使用

    通过解析方法名创建查询 通过前面的例子,读者基本上对解析方法名创建查询的方式有了一个大致的了解,这也是 Spring Data JPA 吸引开发者的一个很重要的因素.该功能其实并非 Spring Da ...

  7. Myeclipse发布第一个jsp页面及web project部署到tomcat上的几种方法

    菜鸟日记: 1:new web project: 2:fix the visiting  path of the tomcat,打开在安装目录下conf目录中的server.xml,在</Hos ...

  8. vue2.0:(六)、移动端像素border的实现和整合引入less文件

    知识点一.如何在手机上看我们制作的移动端页面. 正常我们在电脑上都是按如下图来制作手机页面的: 如果要在手机上面看就不能用localhost了.所以,进入命令行,输入ipconfig查看本地ip地址: ...

  9. python+selenium之验证码的处理

    对于web应用来说,大部分的系统在用户登录时都要求用户输入验证码.验证码的类型很多,有字母数字的,有汉字的.甚至还有需要用户输入一道算术题的答案的.对于系统来说,使用验证码可以有效地防止采用机器猜测方 ...

  10. 【Python图像特征的音乐序列生成】关于mingus一个bug的修复,兼改进情感模型

    mingus在输出midi文件的时候,使用这样的函数: from mingus.containers import NoteContainer from mingus.midi import midi ...