2011年6月20日月曜日

googlemockで引数アサーション

googlemockでクラスや構造体のメンバが正しい値でモック関数が呼び出されているかを確認したい。

struct Param {
    bool flag;
    int value;
};

class Interface {
public:
    virtual ~Interface() { }
    virtual void f(const Param& p) = 0;
};

class Actor {
public:
    Actor(Interface& d) : derived(d) { }
    void DoIt(const Param& p) {
        Param tmp;
        tmp.flag = !(p.flag);
        tmp.value = -1 * p.value;
        derived.f(tmp);
    }
private:
    Interface& derived;
};

確認したいこと

Actor::f()がParam::flagを反転、Param::valueの正負を反転させてからInterface::f()を呼び出していることを確認したい。

Param::operator==()を定義しちゃえば良いじゃんというツッコミはナシ。

順当にgooglemockのマッチャーを使う

TEST(GMockSample, Use_GMock_MemberMathcer) {
    using ::testing::AllOf;
    using ::testing::Eq;
    using ::testing::Field;
    using ::testing::Truly;

    Mock mock;
    Param p = {false, 345};

    Actor actor(mock);

    EXPECT_CALL(mock, f(
        AllOf(
            Field(&Param::flag, Eq(true)),
            Field(&Param::value, Eq(-345))
        )
    ));

    // Act!!
    actor.DoIt(p);
}
フィールドの数が増えてきたら、どうするんだろうね。

boost::bindを使う

TEST(GMockSample, Use_Boost_Bind) {
    using ::testing::Truly;
    using ::boost::bind;

    Mock mock;
    Param p = {false, 345};
    Param expect = {true, -345};

    Actor actor(mock);

    EXPECT_CALL(mock, f(
        Truly(
            bind(EqualParameter(), expect, _1)
        )
    ));

    // Act!!
    actor.DoIt(p);
}
期待値をローカル変数に用意しているのがなぁ。

boost::lambdaを使う

TEST(GMockSample, Use_Boost_Lambda) {
    using ::boost::bind;
    using ::boost::lambda::_1;
    using ::testing::Truly;

    Mock mock;
    Param p = {false, 345};

    Actor actor(mock);

    EXPECT_CALL(mock, f(
        Truly(
            bind(&Param::flag, _1) == true
                && bind(&Param::value, _1) == -345
        )
    ));

    // Act!!
    actor.DoIt(p);
}
なんだか、もう一息な気がする。