Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

怎么取消指定MOCKER #29

Open
lightthgil opened this issue Jul 23, 2021 · 7 comments
Open

怎么取消指定MOCKER #29

lightthgil opened this issue Jul 23, 2021 · 7 comments

Comments

@lightthgil
Copy link

GlobalMockObject::verify(); 或者GlobalMockObject::reset();可以取消所有的MOCKER,但是,如果我想保留一部分MOCKER,只取消另一部分MOCKER,需要怎么做?

@sinojelly
Copy link
Owner

你说的是 C 函数的mock [ 用 MOCKER(func) ] 还是 C++虚函数的mock [ 用 MOCK_METHOD(mocker, method) ]。
如果是前者,可能多个 C 函数,都是统一通过 GlobalMockObject操作的,暂时可能不好单个操作。
如果是后者,可能你针对一个mock对象 mocker,可以单独进行操作。但是一个 mocker 有多个 method 的mock,要取消其中某一个,可能没有现成的方式支持。

我还没详细去看怎么支持单个 mocker 的取消。
基于已有的特性,每个mockder 可以指定 id, 也许有可能通过 指定id的方式,取消一个 mocker。

@lightthgil
Copy link
Author

无论是C函数使用GlobalMockObject::reset();还是C++虚函数使用mock_class_instance.reset(),最终都会调用到

void
ChainableMockMethodContainerImpl::reset()
{
//for_each(methods.begin(), methods.end(), resetMethod);
for(Iterator i = methods.begin(); i != methods.end(); i++)
{
resetMethod(*i);
}
methods.clear();
verified = false;
}

而resetMethod可以删除特定的mock
void resetMethod(ChainableMockMethodContainerImpl::ValueType value)
{
getMethodCore(value)->reset();
// We don't know wether MethodCore is referring a "key" or not,
// so if we delete the key prior to methodCore might result in
// unexpected behavior.
delete getMethodCore(value);
delete getKey(value);
}
}

是否可以将resetMethod通过某种方式暴露出来

@sinojelly
Copy link
Owner

嗯,大概是这个思路。但是要让使用者,可以方便的 reset 指定的mocker 才行。
从你贴的代码来看, ChainableMockMethodContainerImpl::ValueType 这样的类型,用户是不好用的。

所以我说 reset 指定的 mocker, 得先有个办法指定 mocker,然后reset 它。
我能想到的是 mocker 可以指定 id, 所以如果能把 mocker 指定的 id, 与 reset 实现联系起来。
用户就可以用下面方式reset指定的mocker了。
mocker.reset(id)

@darren-zhk
Copy link

老哥这个项目还在维护吗 关于reset这个。可否在一类关键字(stubs)后扩展一个reset?

@sinojelly
Copy link
Owner

老哥这个项目还在维护吗 关于reset这个。可否在一类关键字(stubs)后扩展一个reset?

你说的 .stubs之后,可以.reset 吗? 可能达不到用完一个mocker就取消的效果哦。

有需求,可以在这个issue上+1。还可以在评论中写一下具体场景,为什么需要这个特性。

当然也欢迎提出方案,甚至实现这个特性。

@lightthgil
Copy link
Author

lightthgil commented Jan 7, 2022

老哥这个项目还在维护吗 关于reset这个。可否在一类关键字(stubs)后扩展一个reset?

你说的 .stubs之后,可以.reset 吗? 可能达不到用完一个mocker就取消的效果哦。

有需求,可以在这个issue上+1。还可以在评论中写一下具体场景,为什么需要这个特性。

当然也欢迎提出方案,甚至实现这个特性。

我这边还有这个需求。
大致的应用场景是,由高级开发人员构造一个复杂的场景,模拟真实的环境,里面会有MOCK。然后低级别开发人员基于该场景去写测试用例。测试用例中可能会自己MOCK有些函数,然后自己在测试用例的结尾unmock掉。

举个栗子:

class Scenes_base : public testing::Test {
  public:
    Scenes_base(){};
    ~Scenes_base(){};
    virtual void SetUp() override;
    virtual void TearDown() override;
};
void Scenes_base::SetUp()
{
    // do something
    MOCKER(func1).stubs().will(invoke(fake_func1));
    MOCKER(func2).stubs().will(returnValue(0));
}
void Scenes_base::TearDown()
{
    GlobalMockObject::verify();
}




class Scenes_online : public Scenes_base {
  public:
    Scenes_online(){};
    virtual ~Scenes_online(){};
    virtual void SetUp() override;
    virtual void TearDown() override;;
};

void Scenes_online::SetUp()
{
    Scenes_base::SetUp();
    // do something
}

void Scenes_online::TearDown()
{
    Scenes_base::TearDown();
}

TEST_F(Scenes_online, return_1_offline_when_xxx)
{
    MOCKER(recv_online_state).stubs().will(returnValue(false)).id("recv_online_state_return_false");
    // do something

    EXPECT_NE(get_online_state(), false);
    
    MOCKER(recv_online_state).id("recv_online_state_return_false").reset();    //期望这里取消桩
}

TEST_F(Scenes_online, return_1_online_when_xxx)
{
    MOCKER(recv_online_state).stubs().will(returnValue(true)).id("recv_online_state_return_true");
    // do something

    EXPECT_NE(get_online_state(), true);
    
    MOCKER(recv_online_state).id("recv_online_state_return_true").reset();    //期望这里取消桩
}

实际的应用会比这个例子复杂。但是大致是这个意思,在Scenes_online的几个测试用例中,希望复用基础场景Scene_base构建的环境,测试不同的功能,每个测试可能会有MOCK,如上述两个测试用例Scenes_online.return_1_offline_when_xxxScenes_online.return_1_true_when_xxx,但是每个测试用例跑完后,需要UNMOCK掉自己测试用例中的MOCKER,防止影响下一个测试用例。如果用GlobalMockObject::verify()或者GlobalMockObject::reset(),则同时会unmock掉基础场景Scene_base中的MOCKER,导致场景不可用,所以希望能仅unmock掉自己测试用例的MOCKER

@darren-zhk
Copy link

应用场景:

老哥这个项目还在维护吗 关于reset这个。可否在一类关键字(stubs)后扩展一个reset?

你说的 .stubs之后,可以.reset 吗? 可能达不到用完一个mocker就取消的效果哦。
有需求,可以在这个issue上+1。还可以在评论中写一下具体场景,为什么需要这个特性。
当然也欢迎提出方案,甚至实现这个特性。

我这边还有这个需求。 大致的应用场景是,由高级开发人员构造一个复杂的场景,模拟真实的环境,里面会有MOCK。然后低级别开发人员基于该场景去写测试用例。测试用例中可能会自己MOCK有些函数,然后自己在测试用例的结尾unmock掉。

举个栗子:

class Scenes_base : public testing::Test {
  public:
    Scenes_base(){};
    ~Scenes_base(){};
    virtual void SetUp() override;
    virtual void TearDown() override;
};
void Scenes_base::SetUp()
{
    // do something
    MOCKER(func1).stubs().will(invoke(fake_func1));
    MOCKER(func2).stubs().will(returnValue(0));
}
void Scenes_base::TearDown()
{
    GlobalMockObject::verify();
}




class Scenes_online : public Scenes_base {
  public:
    Scenes_online(){};
    virtual ~Scenes_online(){};
    virtual void SetUp() override;
    virtual void TearDown() override;;
};

void Scenes_online::SetUp()
{
    Scenes_base::SetUp();
    // do something
}

void Scenes_online::TearDown()
{
    Scenes_base::TearDown();
}

TEST_F(Scenes_online, return_1_offline_when_xxx)
{
    MOCKER(recv_online_state).stubs().will(returnValue(false)).id("recv_online_state_return_false");
    // do something

    EXPECT_NE(get_online_state(), false);
    
    MOCKER(recv_online_state).id("recv_online_state_return_false").reset();    //期望这里取消桩
}

TEST_F(Scenes_online, return_1_online_when_xxx)
{
    MOCKER(recv_online_state).stubs().will(returnValue(true)).id("recv_online_state_return_true");
    // do something

    EXPECT_NE(get_online_state(), true);
    
    MOCKER(recv_online_state).id("recv_online_state_return_true").reset();    //期望这里取消桩
}

实际的应用会比这个例子复杂。但是大致是这个意思,在Scenes_online的几个测试用例中,希望复用基础场景Scene_base构建的环境,测试不同的功能,每个测试可能会有MOCK,如上述两个测试用例Scenes_online.return_1_offline_when_xxxScenes_online.return_1_true_when_xxx,但是每个测试用例跑完后,需要UNMOCK掉自己测试用例中的MOCKER,防止影响下一个测试用例。如果用GlobalMockObject::verify()或者GlobalMockObject::reset(),则同时会unmock掉基础场景Scene_base中的MOCKER,导致场景不可用,所以希望能仅unmock掉自己测试用例的MOCKER

看了下实列我觉得取消的桩的方式略显复杂
希望的方式如下:

TEST_F(Scenes_online, return_1_online_when_xxx)
{
    MOCKER(recv_online_state).stubs().will(returnValue(true));
    // do something

    EXPECT_NE(get_online_state(), true);
    
    MOCKER(recv_online_state).reset();    //期望这里取消桩
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants