在测试 Card 和 CardCollection 时使用 GoogleMock 避免依赖关系 class
Using GoogleMock to avoid dependencies when testing a Card and a CardCollection class
我正在学习模拟并且对这些概念相当陌生。为了学习,我正在实现一个 Card
class 和一个 CardCollection
class,这取决于 Card
。因此我创建了一个 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
class ,因为这会在单元测试中引入不需要的依赖项。所以我决定将从 CardCollection::pop
返回的 ICard*
转换为 MockCard*
类型,这样我们就可以使用 getRank()
方法并测试返回的值是 6
.但是,这是 MockCard
而不是 Card
所以 getRank()
实际上 returns 是 0
并且测试失败。
如何将MockCard::getRank()
返回的值设置为6
?更一般地说,在我测试此行为的方法中,您是否可以看到任何明显的陷阱?如果是,您会实施什么作为替代方案?
获得指向new_card
的指针后,您可以使用
ON_CALL(*new_card, getRank()).WillByDefault(Return(6));
制作你的 mock 方法 return 6
我正在学习模拟并且对这些概念相当陌生。为了学习,我正在实现一个 Card
class 和一个 CardCollection
class,这取决于 Card
。因此我创建了一个 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
class ,因为这会在单元测试中引入不需要的依赖项。所以我决定将从 CardCollection::pop
返回的 ICard*
转换为 MockCard*
类型,这样我们就可以使用 getRank()
方法并测试返回的值是 6
.但是,这是 MockCard
而不是 Card
所以 getRank()
实际上 returns 是 0
并且测试失败。
如何将MockCard::getRank()
返回的值设置为6
?更一般地说,在我测试此行为的方法中,您是否可以看到任何明显的陷阱?如果是,您会实施什么作为替代方案?
获得指向new_card
的指针后,您可以使用
ON_CALL(*new_card, getRank()).WillByDefault(Return(6));
制作你的 mock 方法 return 6