【问题标题】:Using GoogleMock to avoid dependencies when testing a Card and a CardCollection class在测试 Card 和 CardCollection 类时使用 GoogleMock 避免依赖关系
【发布时间】:2021-01-03 12:19:22
【问题描述】:

我正在学习模拟,并且对这些概念相当陌生。为了学习,我实现了一个Card 类和一个依赖于CardCardCollection 类。因此我创建了一个MockCard 来测试CardCollection

这是Card.h

    class ICard {
    protected:
        int rank_;
        std::string suit_;
    public:

        ICard(int rank, std::string suit) : rank_(rank), suit_(std::move(suit)) {};

        [[nodiscard]] virtual int getRank() const = 0;

        [[nodiscard]] virtual std::string getSuit() const  = 0;

        friend std::ostream &operator<<(std::ostream &os, const ICard &c);

        bool operator>(const ICard &other) const;

        bool operator<(const ICard &other) const;

        bool operator<=(const ICard &other) const;

        bool operator>=(const ICard &other) const;

        bool operator==(const ICard &other) const;

        bool operator!=(const ICard &other) const;
    };

    class Card : public ICard {
    public:

        Card(int r, std::string s);

        [[nodiscard]] int getRank() const override;

        [[nodiscard]] std::string getSuit() const override;

    };

MockCard.h

#include "gmock/gmock.h"
class MockCard : public ICard {
public:
    MockCard(int rank, std::string suit) : ICard(rank, std::move(suit)){};
    MOCK_METHOD(int, getRank, (), (const, override));
    MOCK_METHOD(std::string, getSuit, (), (const, override));
};

还有CardCollection.h

    #include "Card.h"
    class CardCollection {

    protected:
        vector<ICard *> cards_;
    public:

        CardCollection() = default;

        ~CardCollection() = default;

        explicit CardCollection(vector<ICard*> cards);

        ICard* pop();

    ...

这是我的测试:

#include "gmock/gmock.h"
TEST(CardCollectionTests, TestPop) {
    MockCard card1(6, "C");
    std::vector<ICard*> cards({&card1});
    CardCollection cc(cards);

    // pop the card off the collection, cast to MockCard
    auto* new_card = (MockCard*) cc.pop();

    ASSERT_EQ(6, new_card->getRank());
}

我能想到的最好的测试是验证这张牌是梅花 6。但是我们不能直接使用Card 类,因为这会在单元测试中引入不需要的依赖项。所以我决定将从CardCollection::pop 返回的ICard* 转换为MockCard* 类型,以便我们可以使用getRank() 方法并测试返回的值是6。但是,这是 MockCard 而不是 Card 所以 getRank() 实际上返回 0 并且测试失败。

如何将MockCard::getRank()返回的值设置为6?更一般地说,在我测试这种行为的方法中,您是否可以看到任何明显的缺陷?如果是,您会实施什么替代方案?

【问题讨论】:

  • 您可以使用ON_CALL(*new_card, getRank()).WillByDefault(Return(6)); 使该模拟方法返回6
  • 非常好,谢谢。如果你把它变成答案,我会接受。
  • 好的,我已将其发布为您问题的答案
  • 另外,使用dynamic_cast 向上转换/向下转换比使用类型转换更好也更安全。 dynamic_cast 将在失败时返回一个空指针。

标签: c++ testing mocking tdd googlemock


【解决方案1】:

获得指向new_card的指针后,就可以使用

ON_CALL(*new_card, getRank()).WillByDefault(Return(6));

让你的模拟方法返回6

【讨论】:

    猜你喜欢
    • 2012-01-15
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 2012-05-11
    • 1970-01-01
    • 2016-03-18
    相关资源
    最近更新 更多