方法和模拟同一个类

发布于 2024-11-14 00:53:14 字数 228 浏览 3 评论 0原文

我有两个方法的类,

class A
{
  void Fun()
  {
    if(FunRet()>0){///} else {///}
  } 
  int FunRet()
  { return 4;}
};

我想根据 FunRet 返回的内容来测试 Fun() 方法。所以我想嘲笑 FunRet。 我不想让 FunRet 成为虚拟的。我怎样才能做到这一点?

I have class with 2 methods

class A
{
  void Fun()
  {
    if(FunRet()>0){///} else {///}
  } 
  int FunRet()
  { return 4;}
};

I want to test Fun() method depend on what FunRet returns. So i want to mock FunRet.
I rather don't want make FunRet as virtual. How I can do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

属性 2024-11-21 00:53:14

您可以注入类内依赖项。在这种情况下,让 Fun 接受一个值而不是计算它:

class A
{
  void Fun(int x)
  {
    if(x>0){///} else {///}
  } 
  int FunRet()
  { return 4;}
};

然后您的测试可以将任意值传递到 Fun() 中。如果您需要强制正确使用,请编写一个公共版本以在您的 API 中公开,并编写一个私有版本以进行测试:

class A {
 public:
  void Fun() { return Fun(FunRet()); }
 private:
  void Fun(int x);  // for testing.
};

You can inject intra-class dependencies. In this case, make Fun accept a value instead of computing it:

class A
{
  void Fun(int x)
  {
    if(x>0){///} else {///}
  } 
  int FunRet()
  { return 4;}
};

Then your tests can pass arbitrary values into Fun(). If you need to enforce correct use, write a public version to expose in your API and a private version for testing:

class A {
 public:
  void Fun() { return Fun(FunRet()); }
 private:
  void Fun(int x);  // for testing.
};
羁拥 2024-11-21 00:53:14

您可以将 Fun 方法提取到实现接口的计算器类中。您应该在构造函数中将该接口的实例传递给 A 类。

在测试中,您可以让其他类实现该接口,并返回其他值。

此方法还有一个很大的优点,即您可以将计算值和使用计算值的关注点分开。

class A {
public:
   A (IFunCalc calc) { m_calc = calc; }
   void Fun { if calc.FunRet() > 4 ... }
private:
   IFunCalc m_calc;
}
class FunCalc : IFunCulc {
public:
   int FunRet { return 4; }
}
class FunCalc4Test : IFunCalc {
public:
   int FunRet { return 27; }
}

You could extract the Fun method into a calculator class that implements an interface. You should pass an instance of that interface to class A at constructor.

In testing you could have other classes implementing that interface, that return other values.

This method also have the big advantage, that you seperate the concerns of calculating a value and using the calculated value.

class A {
public:
   A (IFunCalc calc) { m_calc = calc; }
   void Fun { if calc.FunRet() > 4 ... }
private:
   IFunCalc m_calc;
}
class FunCalc : IFunCulc {
public:
   int FunRet { return 4; }
}
class FunCalc4Test : IFunCalc {
public:
   int FunRet { return 27; }
}
洒一地阳光 2024-11-21 00:53:14

我认为你错过了 this 指针。

... if ( this->FunRet() > 0 ) { ...

I think you're missing the this pointer.

... if ( this->FunRet() > 0 ) { ...

差↓一点笑了 2024-11-21 00:53:14

如果您使用依赖项注入并对被测对象进行模板化,则可以使用模拟对象而不必使用虚函数。

class AParameters
{
public:
  int FunRet()
  { return 4;}
};

class MockAParameters
{
public:
  MOCK_METHOD0(FunRet, int());
};

template<class Parameters>
class AImpl
{
public:
   AImpl(Parameters& parameters):parameters(parameters){}

  void Fun()
  {
    if(parameters.FunRet()>0){///} else {///}
  } 

private:
   Parameters& parameters;
};

typedef AImpl<AParameters> A;
typedef AImpl<MockAParameters> ATestObject;

void Test::funUsesFunRet()
{
    MockAParameters params;
    EXPECT_CALL(params, FunRet());
    ATestObject object(params);
    object.Fun();
}

If you use dependency injection and template your object under test, you can use mock objects without having to use virtual functions.

class AParameters
{
public:
  int FunRet()
  { return 4;}
};

class MockAParameters
{
public:
  MOCK_METHOD0(FunRet, int());
};

template<class Parameters>
class AImpl
{
public:
   AImpl(Parameters& parameters):parameters(parameters){}

  void Fun()
  {
    if(parameters.FunRet()>0){///} else {///}
  } 

private:
   Parameters& parameters;
};

typedef AImpl<AParameters> A;
typedef AImpl<MockAParameters> ATestObject;

void Test::funUsesFunRet()
{
    MockAParameters params;
    EXPECT_CALL(params, FunRet());
    ATestObject object(params);
    object.Fun();
}
安静 2024-11-21 00:53:14

我相信 FunRetFun 的内部实现细节。因此,Fun 不需要与 FunRet 分开进行测试。只需测试 Fun 而不必担心它调用 FunRet 的事实。

I believe FunRet is an internal implementation detail of Fun. As a result, Fun does not need to be tested in isolation from FunRet. Just test Fun and don't worry about the fact it calls FunRet.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文