开发者

Method and mock with same class

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?


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.
};


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; }
}


I think you're missing the this pointer.

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


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();
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜