Clay Dowling
class CartItem {
private:
string name;
int quantity;
double price;
public:
const string &getName() const;
void setName(const string &name);
int getQuantity() const;
void setQuantity(int quantity);
double getPrice() const;
void setPrice(double price);
double getItemTotal();
};
TEST_F(CITest, getLineTotal_withQuantityOne_returnsItemPrice)
{
item.setName(ITEM_NAME);
item.setPrice(3.14);
item.setQuantity(1);
ASSERT_EQ(item.getItemTotal(), 3.14);
}
double CartItem::getItemTotal() {
return 3.14;
}
TEST_F(CITest, getLineTotal_withDifferentPrice_returnsItemPrice)
{
item.setName(ITEM_NAME);
item.setPrice(2.71);
item.setQuantity(2);
ASSERT_EQ(item.getItemTotal(), 5.42);
}
double CartItem::getItemTotal() {
return quantity * price;
}
class Cart {
public:
int itemCount();
void addItem(unique_ptr<CartItem> item);
};
TEST_F(CTest, itemCount_afterOneItemAdded_returnsOne) {
cart.addItem(make_unique<CartItem>(
CartItem(ITEM_NAME, 1, 3.14)));
ASSERT_EQ(cart.itemCount(), 1);
}
void Cart::addItem(unique_ptr<CartItem> item) {
items.push_back(move(item));
}
class DataResult {
public:
virtual shared_ptr<vector<string>> getFields() = 0;
virtual shared_ptr<vector<string>> getNext() = 0;
virtual bool eof() = 0;
};
class DataStore {
public:
virtual void setQuery(string sql) = 0;
virtual void setParam(string param, string value) = 0;
virtual void setParam(string param, int value) = 0;
virtual void setParam(string param, double value) = 0;
virtual DataResult execute() = 0;
};
#include "DataResult.h "
class MockDataResult : public DataResult {
public:
virtual shared_ptr<vector<string>> getFields() override;
virtual shared_ptr<vector<string>> getNext() override;
virtual bool eof() override;
void addNext(int fieldCount, ...);
void setFields(int fieldCount, ...);
private:
queue<shared_ptr<vector<string>>> dataset;
shared_ptr<vector<string>> fields;
};
shared_ptr<vector<string>> MockDataResult::getFields() {
return fields;
}
void MockDataResult::setFields(int fieldCount, ...) {
vector<string> f;
va_list args;
va_start(args, fieldCount);
for (int i = 0; i < fieldCount; ++i) {
f.push_back(va_arg(args, const char *));
}
va_end(args);
fields = make_shared<vector<string>>(f);
}
void MockDataResult::addNext(int fieldCount, ...) {
vector<string> row;
va_list args;
va_start(args, fieldCount);
for (int i = 0; i < fieldCount; ++i) {
row.push_back(va_arg(args, const char *));
}
va_end(args);
dataset.push(make_shared<vector<string>>(row));
}
shared_ptr<vector<string>> MockDataResult::getNext() {
auto row = dataset.front();
dataset.pop();
return row;
}
bool MockDataResult::eof() { return dataset.empty(); }
TEST_F(CITest, inputStream_givenAllFields_populatesCartItem)
{
result.setFields(3, "name ", "price ", "quantity ");
result.addNext(3, ITEM_NAME, "3.14 ", "1 ");
result >> item;
ASSERT_EQ(item.getName(), ITEM_NAME);
ASSERT_EQ(item.getPrice(), 3.14);
ASSERT_EQ(item.getQuantity(), 1);
}
DataResult& operator>>(DataResult& in, CartItem& item) {
⋮
auto fields = in.getFields();
for(int i=0; i < fields->size(); ++i) {
if ("name " == fields->at(i)) name_idx = i;
if ("price " == fields->at(i)) price_idx = i;
if ("quantity " == fields->at(i)) quantity_idx = i;
}
⋮
}
DataResult& operator>>(DataResult& in, CartItem& item) {
⋮
auto row_ptr = in.getNext();
auto row = *row_ptr;
item.setName(row[name_idx]);
item.setQuantity(stoi(row[quantity_idx]));
item.setPrice(stod(row[price_idx], nullptr));
return in;
}
class MockDataStore : public DataStore {
public:
MockDataStore();
void setQuery(string sql) override;
void setParam(string param, string value) override;
void setParam(string param, int value) override;
void setParam(string param, double value) override;
DataResult execute() override;
private:
map<string, string> string_params;
map<string, int> int_params;
map<string, double> double_params;
bool execute_called;
};
void MockDataStore::setQuery(string sql) {
this->sql = sql;
string_params.clear();
int_params.clear();
double_params.clear();
}
void MockDataStore::setParam(string param, string value) {
string_params[param] = value;
}
void MockDataStore::setParam(string param, int value) {
int_params[param] = value;
}
void MockDataStore::setParam(string param, double value) {
double_params[param] = value;
}
string MockDataStore::getSql() {
return sql;
}
string MockDataStore::getStringParam(string param) {
return string_params.at(param);
}
int MockDataStore::getIntParam(string param) {
return int_params.at(param);
}
double MockDataStore::getDoubleParam(string param) {
return double_params.at(param);
}
bool MockDataStore::executeWasCalled() {
return execute_called;
}
TEST_F(CITest, outputStream_byDefault_setsQueryParameters) {
item.setName(ITEM_NAME);
item.setPrice(3.14);
item.setQuantity(5);
store << item;
ASSERT_EQ(store.getStringParam(":name "), ITEM_NAME);
ASSERT_EQ(store.getIntParam(":quantity "), 5);
ASSERT_EQ(store.getDoubleParam(":price "), 3.14);
ASSERT_TRUE(store.executeWasCalled());
}
DataStore& operator<<(DataStore& out, CartItem& item) {
out.setParam(":name ", item.getName());
out.setParam(":price ", item.getPrice());
out.setParam(":quantity ", item.getQuantity());
out.execute();
return out;
}
Question about your specific situation?
What do you want to know more about?
Clay Dowling
claydowling.com