Skip to content

Commit 909978a

Browse files
committed
Add PricePlanComparatorControllerTest and fix some bug
1 parent 1b3a739 commit 909978a

File tree

6 files changed

+120
-12
lines changed

6 files changed

+120
-12
lines changed

rest/controller/PricePlanComparatorController.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ class PricePlanComparatorController {
3131
res.set(http::field::content_type, "application/json");
3232
res.keep_alive(req.keep_alive());
3333
nlohmann::json j;
34-
j["pricePlanComparisons"] = {{"price-plan-0", double(costs.value()["price-plan-0"]) / 10000},
35-
{"price-plan-1", double(costs.value()["price-plan-1"]) / 10000},
36-
{"price-plan-2", double(costs.value()["price-plan-2"]) / 10000}};
34+
for (auto &ele : costs.value()) {
35+
ele.second /= 10000;
36+
}
37+
j["pricePlanComparisons"] = costs.value();
3738
j["pricePlanId"] = current_price_plans[meterId];
3839
res.body() = j.dump();
3940
res.prepare_payload();
@@ -43,17 +44,22 @@ class PricePlanComparatorController {
4344
http::response<http::string_body> Recommend(const http::request<http::string_body> &req,
4445
const std::vector<std::string> &queries) {
4546
const auto &meterId = queries[0];
46-
int limit = std::stoi(queries[2]);
47+
std::optional<int> maybeLimit;
48+
if (queries.size() > 2){
49+
maybeLimit = std::stoi(queries[2]);
50+
}
4751
auto costs = pricePlanService.getConsumptionCostOfElectricityReadingsForEachPricePlan(meterId);
4852

4953
if (!costs) {
5054
return {http::status::not_found, req.version()};
5155
}
5256

53-
std::vector<std::pair<std::string, float>> ordered_costs{costs->begin(), costs->end()};
57+
std::vector<std::pair<std::string, double>> ordered_costs{costs->begin(), costs->end()};
5458
std::sort(ordered_costs.begin(), ordered_costs.end(),
5559
[](auto &cost_a, auto &cost_b) { return cost_a.second < cost_b.second; });
56-
ordered_costs.resize(std::min(limit, int(ordered_costs.size())));
60+
if (maybeLimit.has_value()) {
61+
ordered_costs.resize(std::min(maybeLimit.value(), int(ordered_costs.size())));
62+
}
5763

5864
http::response<http::string_body> res{http::status::ok, req.version()};
5965
res.set(http::field::content_type, "application/json");

rest/service/PricePlanService.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#define DEVELOPER_JOYOFENERGY_CPP_BEAST_PRICEPLANSERVICE_H
33

44
#include <configuration.h>
5-
#include <controller/MeterReadingController.h>
65
#include <domain/ElectricityReading.h>
76
#include <domain/PricePlan.h>
87
#include <service/MeterReadingService.h>

test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ find_package(nlohmann_json REQUIRED)
55
target_link_libraries(endpoint_test PRIVATE GTest::gmock_main nlohmann_json::nlohmann_json rest)
66

77
add_executable(controller_test)
8-
target_sources(controller_test PRIVATE controller/MeterReadingControllerTest.cpp)
8+
target_sources(controller_test PRIVATE controller/MeterReadingControllerTest.cpp controller/PricePlanComparatorControllerTest.cpp)
99
target_link_libraries(controller_test PRIVATE GTest::gmock_main nlohmann_json::nlohmann_json rest)
1010

1111
add_test(endpoint_test endpoint_test)

test/ReadingTest.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include <nlohmann/json.hpp>
22

3-
#include "domain/ElectricityReading.h"
43
#include "generator.h"
54
#include "test/EndpointTest.h"
65

test/controller/MeterReadingControllerTest.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include <gmock/gmock.h>
2-
#include <rest/configuration.h>
32
#include <rest/controller/MeterReadingController.h>
43

54
#include <boost/beast/http.hpp>
@@ -18,7 +17,7 @@ class MeterReadingControllerTest : public ::testing::Test {
1817
MeterReadingController controller{electricityReadingService, meterReadingService};
1918

2019
http::request<http::string_body> BuildRequest(http::verb verb, boost::string_view target, const json &request_body) {
21-
http::request<http::string_body> req{http::verb::post, "/readings/store", 11};
20+
http::request<http::string_body> req{verb, target, 11};
2221
req.set(http::field::content_type, "application/json");
2322
req.body() = request_body.dump();
2423
req.prepare_payload();
@@ -128,7 +127,7 @@ TEST_F(MeterReadingControllerTest, StoreShouldStoreAssociatedWithUserGivenMeterR
128127
}
129128

130129
TEST_F(MeterReadingControllerTest, ReadShouldReturnNotFoundGivenMeterIdThatIsNotRecognised) {
131-
auto req = BuildRequest(http::verb::post, "/readings/store", R"({})"_json);
130+
http::request<http::string_body> req;
132131
std::vector<std::string> queries = {"smart-meter-0"};
133132

134133
auto response = controller.Read(req, queries);
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#include <gmock/gmock.h>
2+
#include <rest/controller/PricePlanComparatorController.h>
3+
#include <rest/configuration.h>
4+
#include <string>
5+
6+
#include <boost/beast/http.hpp>
7+
#include <nlohmann/json.hpp>
8+
9+
using nlohmann::json;
10+
using ::testing::Eq;
11+
12+
class PricePlanComparatorControllerTest : public ::testing::Test {
13+
protected:
14+
std::unordered_map<std::string, std::vector<ElectricityReading>> meterAssociatedReadings;
15+
MeterReadingService meterReadingService{meterAssociatedReadings};
16+
std::vector<PricePlan> price_plans = pricePlans();
17+
PricePlanService pricePlanService{price_plans, meterReadingService};
18+
PricePlanComparatorController controller{pricePlanService};
19+
};
20+
21+
TEST_F(PricePlanComparatorControllerTest, CompareShouldCalculateCostForMeterReadingsForEveryPricePlan) {
22+
const std::string smart_meter_id = "smart-meter-0";
23+
std::vector<ElectricityReading> readings = {
24+
{std::chrono::system_clock::now() - std::chrono::seconds(3600), 15 * 10000},
25+
{std::chrono::system_clock::now(), 5 * 10000}
26+
};
27+
meterReadingService.storeReadings(smart_meter_id, readings);
28+
http::request<http::string_body> req;
29+
std::vector<std::string> queries = {smart_meter_id};
30+
31+
auto response = controller.Compare(req, queries);
32+
33+
auto body = json::parse(response.body());
34+
EXPECT_THAT(body["pricePlanId"], Eq("price-plan-0"));
35+
EXPECT_THAT(body["pricePlanComparisons"]["price-plan-0"], Eq(100));
36+
EXPECT_THAT(body["pricePlanComparisons"]["price-plan-1"], Eq(20));
37+
EXPECT_THAT(body["pricePlanComparisons"]["price-plan-2"], Eq(10));
38+
}
39+
40+
TEST_F(PricePlanComparatorControllerTest, RecommandShouldRecommandCheapestPricePlansNoLimitForMeterUsage) {
41+
const std::string smart_meter_id = "smart-meter-0";
42+
std::vector<ElectricityReading> readings = {
43+
{std::chrono::system_clock::now() - std::chrono::seconds(1800), 35 * 10000},
44+
{std::chrono::system_clock::now(), 3 * 10000}
45+
};
46+
meterReadingService.storeReadings(smart_meter_id, readings);
47+
http::request<http::string_body> req;
48+
std::vector<std::string> queries = {smart_meter_id};
49+
50+
auto response = controller.Recommend(req, queries);
51+
52+
auto body = json::parse(response.body());
53+
auto recommend = body["recommend"];
54+
EXPECT_THAT(recommend.size(), Eq(3));
55+
EXPECT_THAT(body["recommend"][0]["price-plan-2"], Eq(38));
56+
EXPECT_THAT(body["recommend"][1]["price-plan-1"], Eq(76));
57+
EXPECT_THAT(body["recommend"][2]["price-plan-0"], Eq(380));
58+
}
59+
60+
TEST_F(PricePlanComparatorControllerTest, RecommandShouldRecommendLimitedCheapestPricePlansForMeterUsage) {
61+
const std::string smart_meter_id = "smart-meter-0";
62+
std::vector<ElectricityReading> readings = {
63+
{std::chrono::system_clock::now() - std::chrono::seconds(2700), 5 * 10000},
64+
{std::chrono::system_clock::now(), 20 * 10000}
65+
};
66+
meterReadingService.storeReadings(smart_meter_id, readings);
67+
http::request<http::string_body> req;
68+
std::vector<std::string> queries = {smart_meter_id, "limit", "2"};
69+
70+
auto response = controller.Recommend(req, queries);
71+
72+
auto body = json::parse(response.body());
73+
auto recommend = body["recommend"];
74+
EXPECT_THAT(recommend.size(), Eq(2));
75+
EXPECT_THAT(body["recommend"][0]["price-plan-2"], Eq(16.6666));
76+
EXPECT_THAT(body["recommend"][1]["price-plan-1"], Eq(33.3332));
77+
}
78+
79+
TEST_F(PricePlanComparatorControllerTest, RecommandShouldRecommendCheapestPricePlansMoreThanLimitAvailableForMeterUsage) {
80+
const std::string smart_meter_id = "smart-meter-0";
81+
std::vector<ElectricityReading> readings = {
82+
{std::chrono::system_clock::now() - std::chrono::seconds(3600), 25 * 10000},
83+
{std::chrono::system_clock::now(), 3 * 10000}
84+
};
85+
meterReadingService.storeReadings(smart_meter_id, readings);
86+
http::request<http::string_body> req;
87+
std::vector<std::string> queries = {smart_meter_id, "limit", "5"};
88+
89+
auto response = controller.Recommend(req, queries);
90+
91+
auto body = json::parse(response.body());
92+
auto recommend = body["recommend"];
93+
EXPECT_THAT(recommend.size(), Eq(3));
94+
EXPECT_THAT(body["recommend"][0]["price-plan-2"], Eq(14));
95+
EXPECT_THAT(body["recommend"][1]["price-plan-1"], Eq(28));
96+
EXPECT_THAT(body["recommend"][2]["price-plan-0"], Eq(140));
97+
}
98+
TEST_F(PricePlanComparatorControllerTest, CompareShouldReturnNotFoundGivenNoMatchingMeterId) {
99+
http::request<http::string_body> req;
100+
std::vector<std::string> queries = {"meter-id-not-exist"};
101+
102+
auto response = controller.Compare(req, queries);
103+
104+
EXPECT_THAT(response.result(), Eq(http::status::not_found));
105+
}

0 commit comments

Comments
 (0)