From bb540e6d8025593045386b41ec84be8736570b6e Mon Sep 17 00:00:00 2001 From: "Tian L." <60599517+tian-lt@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:12:13 +0800 Subject: [PATCH] Decouple with a mocked service (#2256) * refactor * build succeed * mock web failures * mock awaitable * resolve comment * improve scope guard * resolve a comment --- src/CalcViewModel/ApplicationViewModel.cpp | 4 +- src/CalcViewModel/CalcViewModel.vcxproj | 18 -- .../CalcViewModel.vcxproj.filters | 6 - .../DataLoaders/CurrencyDataLoader.cpp | 71 +++--- .../DataLoaders/CurrencyDataLoader.h | 8 +- .../DataLoaders/CurrencyHttpClient.cpp | 176 ++++++++++--- .../DataLoaders/CurrencyHttpClient.h | 50 ++-- .../DataLoaders/DataLoaderMockConstants.h | 13 - .../DataLoaders/ICurrencyHttpClient.h | 24 -- .../CalcViewModelCopyForUT.vcxproj | 29 +-- .../CalcViewModelCopyForUT.vcxproj.filters | 6 - .../DataLoaders/CurrencyHttpClient.cpp | 43 ++++ .../CalculatorUnitTests.vcxproj | 2 - .../CalculatorUnitTests.vcxproj.filters | 9 - .../CurrencyConverterUnitTests.cpp | 240 +++++++----------- .../Mocks/CurrencyHttpClient.cpp | 55 ---- .../Mocks/CurrencyHttpClient.h | 90 ------- src/CalculatorUnitTests/pch.h | 1 - 18 files changed, 345 insertions(+), 500 deletions(-) delete mode 100644 src/CalcViewModel/DataLoaders/DataLoaderMockConstants.h delete mode 100644 src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h create mode 100644 src/CalcViewModelCopyForUT/DataLoaders/CurrencyHttpClient.cpp delete mode 100644 src/CalculatorUnitTests/Mocks/CurrencyHttpClient.cpp delete mode 100644 src/CalculatorUnitTests/Mocks/CurrencyHttpClient.h diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index f2835fb4..62035c97 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -171,8 +171,8 @@ void ApplicationViewModel::OnModeChanged() if (!m_ConverterViewModel) { auto dataLoader = std::make_shared(ref new GeographicRegion()); - auto currencyDataLoader = std::make_shared(std::make_unique()); - m_ConverterViewModel = ref new UnitConverterViewModel(std::make_shared(dataLoader, currencyDataLoader)); + m_ConverterViewModel = + ref new UnitConverterViewModel(std::make_shared(dataLoader, std::make_shared())); } m_ConverterViewModel->Mode = m_mode; diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj index aedd8d8f..3e17838a 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj +++ b/src/CalcViewModel/CalcViewModel.vcxproj @@ -325,7 +325,6 @@ - @@ -396,23 +395,6 @@ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed} - - - /DUSE_MOCK_DATA %(AdditionalOptions) - - - - - - - - - - - - - - diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters index 9de55c39..8dd500c0 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj.filters +++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters @@ -171,12 +171,6 @@ DataLoaders - - DataLoaders - - - DataLoaders - DataLoaders diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp index 9a9787c2..5e627287 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp @@ -89,9 +89,8 @@ namespace CalculatorApp } } -CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr client, const wchar_t* forcedResponseLanguage) - : m_client(move(client)) - , m_loadStatus(CurrencyLoadStatus::NotLoaded) +CurrencyDataLoader::CurrencyDataLoader(const wchar_t* forcedResponseLanguage) + : m_loadStatus(CurrencyLoadStatus::NotLoaded) , m_responseLanguage(L"en-US") , m_ratioFormat(L"") , m_timestampFormat(L"") @@ -122,12 +121,7 @@ CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr clie } } - if (m_client != nullptr) - { - m_client->SetSourceCurrencyCode(StringReference(DefaultCurrencyCode.data())); - m_client->SetResponseLanguage(m_responseLanguage); - } - + m_client.Initialize(StringReference{ DefaultCurrencyCode.data() }, m_responseLanguage); auto localizationService = LocalizationService::GetInstance(); if (CoreWindow::GetForCurrentThread() != nullptr) { @@ -199,26 +193,29 @@ void CurrencyDataLoader::LoadData() if (!LoadFinished()) { RegisterForNetworkBehaviorChanges(); - create_task([this]() -> task { - vector()>> loadFunctions = { - [this]() { return TryLoadDataFromCacheAsync(); }, - [this]() { return TryLoadDataFromWebAsync(); }, - }; - - bool didLoad = false; - for (auto& f : loadFunctions) + create_task( + [this]() -> task { - didLoad = co_await f(); - if (didLoad) - { - break; - } - } + vector()>> loadFunctions = { + [this]() { return TryLoadDataFromCacheAsync(); }, + [this]() { return TryLoadDataFromWebAsync(); }, + }; - co_return didLoad; - }) + bool didLoad = false; + for (auto& f : loadFunctions) + { + didLoad = co_await f(); + if (didLoad) + { + break; + } + } + + co_return didLoad; + }) .then( - [this](bool didLoad) { + [this](bool didLoad) + { UpdateDisplayedTimestamp(); NotifyDataLoadFinished(didLoad); }, @@ -283,9 +280,7 @@ double CurrencyDataLoader::RoundCurrencyRatio(double ratio) int numberDecimals = FORMATTER_RATE_MIN_DECIMALS; if (ratio < 1) { - numberDecimals = max( - FORMATTER_RATE_MIN_DECIMALS, - (int)(-log10(ratio)) + FORMATTER_RATE_MIN_SIGNIFICANT_DECIMALS); + numberDecimals = max(FORMATTER_RATE_MIN_DECIMALS, (int)(-log10(ratio)) + FORMATTER_RATE_MIN_SIGNIFICANT_DECIMALS); } unsigned long long scale = (unsigned long long)powl(10l, numberDecimals); @@ -314,8 +309,7 @@ pair CurrencyDataLoader::GetCurrencyRatioEquality(_In_ const U auto ratioString = LocalizationStringUtil::GetLocalizedString( m_ratioFormat, digitSymbol, StringReference(unit1.abbreviation.c_str()), roundedFormat, StringReference(unit2.abbreviation.c_str())); - auto accessibleRatioString = - LocalizationStringUtil::GetLocalizedString( + auto accessibleRatioString = LocalizationStringUtil::GetLocalizedString( m_ratioFormat, digitSymbol, StringReference(unit1.accessibleName.c_str()), roundedFormat, StringReference(unit2.accessibleName.c_str())); return make_pair(ratioString->Data(), accessibleRatioString->Data()); @@ -415,18 +409,13 @@ future CurrencyDataLoader::TryLoadDataFromWebAsync() { ResetLoadStatus(); - if (m_client == nullptr) - { - co_return false; - } - if (m_networkAccessBehavior == NetworkAccessBehavior::Offline || (m_networkAccessBehavior == NetworkAccessBehavior::OptIn && !m_meteredOverrideSet)) { co_return false; } - String ^ staticDataResponse = co_await m_client->GetCurrencyMetadata(); - String ^ allRatiosResponse = co_await m_client->GetCurrencyRatios(); + String ^ staticDataResponse = co_await m_client.GetCurrencyMetadataAsync(); + String ^ allRatiosResponse = co_await m_client.GetCurrencyRatiosAsync(); if (staticDataResponse == nullptr || allRatiosResponse == nullptr) { co_return false; @@ -550,9 +539,7 @@ bool CurrencyDataLoader::TryParseStaticData(_In_ String ^ rawJson, _Inout_ vecto staticData[i] = CurrencyStaticData{ countryCode, countryName, currencyCode, currencyName, currencySymbol }; } - auto sortCountryNames = [](const UCM::CurrencyStaticData & s) { - return ref new String(s.countryName.c_str()); - }; + auto sortCountryNames = [](const UCM::CurrencyStaticData& s) { return ref new String(s.countryName.c_str()); }; LocalizationService::GetInstance()->Sort(staticData, sortCountryNames); @@ -577,7 +564,7 @@ bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String ^ rawJson, _Inout_ Cu { obj = data->GetAt(i)->GetObject(); } - catch (COMException^ e) + catch (COMException ^ e) { if (e->HResult == E_ILLEGAL_METHOD_CALL) { diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h index 6ee878be..99913dd8 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h @@ -5,7 +5,7 @@ #include "CalcManager/UnitConverter.h" #include "Common/NetworkManager.h" -#include "ICurrencyHttpClient.h" +#include "CurrencyHttpClient.h" namespace CalculatorApp { @@ -54,9 +54,7 @@ namespace CalculatorApp class CurrencyDataLoader : public UCM::IConverterDataLoader, public UCM::ICurrencyConverterDataLoader { public: - CurrencyDataLoader( - _In_ std::unique_ptr client, - const wchar_t* overrideLanguage = nullptr); + CurrencyDataLoader(const wchar_t* overrideLanguage = nullptr); ~CurrencyDataLoader(); bool LoadFinished(); @@ -114,7 +112,7 @@ namespace CalculatorApp private: Platform::String ^ m_responseLanguage; - std::unique_ptr m_client; + CurrencyHttpClient m_client; bool m_isRtlLanguage; diff --git a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp index 39786f32..d53c525f 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp +++ b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp @@ -4,47 +4,145 @@ #include "pch.h" #include "CurrencyHttpClient.h" -#ifdef USE_MOCK_DATA -#include "DataLoaderMockConstants.h" -#else -#include "DataLoaderConstants.h" -#endif - -using namespace CalculatorApp::DataLoaders; -using namespace CalculatorApp::ViewModel::DataLoaders; -using namespace Platform; -using namespace std; -using namespace Windows::Foundation; -using namespace Windows::Web::Http; - -CurrencyHttpClient::CurrencyHttpClient() - : m_client(ref new HttpClient()) - , m_responseLanguage(L"en-US") +namespace { -} + constexpr auto MockCurrencyConverterData = LR"( +[ + { + "An": "MAR", + "Rt": 1.00 + }, + { + "An": "MON", + "Rt": 0.50 + }, + { + "An": "NEP", + "Rt": 0.00125 + }, + { + "An": "SAT", + "Rt": 0.25 + }, + { + "An": "URA", + "Rt": 2.75 + }, + { + "An": "VEN", + "Rt": 900.00 + }, + { + "An": "JUP", + "Rt": 1.23456789123456789 + }, + { + "An": "MER", + "Rt": 2.00 + }, + { + "An": "JPY", + "Rt": 0.00125 + }, + { + "An": "JOD", + "Rt": 0.25 + } +])"; -void CurrencyHttpClient::SetSourceCurrencyCode(String ^ sourceCurrencyCode) + constexpr auto MockCurrencyStaticData = LR"( +[ + { + "CountryCode": "MAR", + "CountryName": "Mars", + "CurrencyCode": "MAR", + "CurrencyName": "The Martian Dollar", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "MON", + "CountryName": "Moon", + "CurrencyCode": "MON", + "CurrencyName": "Moon Bucks", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "NEP", + "CountryName": "Neptune", + "CurrencyCode": "NEP", + "CurrencyName": "Space Coins", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "SAT", + "CountryName": "Saturn", + "CurrencyCode": "SAT", + "CurrencyName": "Rings", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "URA", + "CountryName": "Uranus", + "CurrencyCode": "URA", + "CurrencyName": "Galaxy Credits", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "VEN", + "CountryName": "Venus", + "CurrencyCode": "VEN", + "CurrencyName": "Venusian Seashells", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "JUP", + "CountryName": "Jupiter", + "CurrencyCode": "JUP", + "CurrencyName": "Gas Money", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "MER", + "CountryName": "Mercury", + "CurrencyCode": "MER", + "CurrencyName": "Sun Notes", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "TEST1", + "CountryName": "Test No Fractional Digits", + "CurrencyCode": "JPY", + "CurrencyName": "Test No Fractional Digits", + "CurrencySymbol": "¤" + }, + { + "CountryCode": "TEST2", + "CountryName": "Test Fractional Digits", + "CurrencyCode": "JOD", + "CurrencyName": "Test Fractional Digits", + "CurrencySymbol": "¤" + } +])"; +} // namespace + +namespace CalculatorApp::ViewModel::DataLoaders { - m_sourceCurrencyCode = sourceCurrencyCode; -} + bool CurrencyHttpClient::ForceWebFailure = false; + void CurrencyHttpClient::Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage) + { + m_sourceCurrencyCode = sourceCurrencyCode; + m_responseLanguage = responseLanguage; + } -void CurrencyHttpClient::SetResponseLanguage(String ^ responseLanguage) -{ - m_responseLanguage = responseLanguage; -} + MockAwaitable CurrencyHttpClient::GetCurrencyMetadataAsync() const + { + (void)m_responseLanguage; // to be used in production. + return MockAwaitable{ ref new Platform::String(MockCurrencyStaticData) }; + } -IAsyncOperationWithProgress ^ CurrencyHttpClient::GetCurrencyMetadata() -{ - wstring uri = wstring{ sc_MetadataUriLocalizeFor } + m_responseLanguage->Data(); - auto metadataUri = ref new Uri(StringReference(uri.c_str())); - - return m_client->GetStringAsync(metadataUri); -} - -IAsyncOperationWithProgress ^ CurrencyHttpClient::GetCurrencyRatios() -{ - wstring uri = wstring{ sc_RatiosUriRelativeTo } + m_sourceCurrencyCode->Data(); - auto ratiosUri = ref new Uri(StringReference(uri.c_str())); - - return m_client->GetStringAsync(ratiosUri); -} + MockAwaitable CurrencyHttpClient::GetCurrencyRatiosAsync() const + { + (void)m_sourceCurrencyCode; // to be used in production. + return MockAwaitable{ ref new Platform::String(MockCurrencyConverterData) }; + } +} // namespace CalculatorApp::ViewModel::DataLoaders diff --git a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h index 8f667c7c..354dc685 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h +++ b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h @@ -1,29 +1,43 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once +#include -#include "ICurrencyHttpClient.h" - -namespace CalculatorApp +namespace CalculatorApp::ViewModel::DataLoaders { - namespace ViewModel::DataLoaders + template + struct MockAwaitable { - class CurrencyHttpClient : public ICurrencyHttpClient + T Value; + + bool await_ready() const noexcept { - public: - CurrencyHttpClient(); + return true; + } - void SetSourceCurrencyCode(Platform::String ^ sourceCurrencyCode) override; - void SetResponseLanguage(Platform::String ^ responseLanguage) override; + void await_suspend(std::experimental::coroutine_handle<>) const noexcept + { + assert(false && "not implemented."); + } - Windows::Foundation::IAsyncOperationWithProgress ^ GetCurrencyMetadata() override; - Windows::Foundation::IAsyncOperationWithProgress ^ GetCurrencyRatios() override; + T await_resume() noexcept + { + return std::move(Value); + } + }; - private: - Windows::Web::Http::HttpClient ^ m_client; - Platform::String ^ m_responseLanguage; - Platform::String ^ m_sourceCurrencyCode; - }; - } + class CurrencyHttpClient + { + public: + static bool ForceWebFailure; + void Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage); + + MockAwaitable GetCurrencyMetadataAsync() const; + MockAwaitable GetCurrencyRatiosAsync() const; + + private: + Platform::String ^ m_sourceCurrencyCode; + Platform::String ^ m_responseLanguage; + }; } diff --git a/src/CalcViewModel/DataLoaders/DataLoaderMockConstants.h b/src/CalcViewModel/DataLoaders/DataLoaderMockConstants.h deleted file mode 100644 index 02e7e349..00000000 --- a/src/CalcViewModel/DataLoaders/DataLoaderMockConstants.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace DataLoaders - { - static constexpr auto sc_MetadataUriLocalizeFor = L"https://go.microsoft.com/fwlink/?linkid=2091028&localizeFor="; - static constexpr auto sc_RatiosUriRelativeTo = L"https://go.microsoft.com/fwlink/?linkid=2091307&localCurrency="; - } -} diff --git a/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h b/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h deleted file mode 100644 index 84104b7b..00000000 --- a/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace ViewModel::DataLoaders - { - class ICurrencyHttpClient - { - public: - virtual ~ICurrencyHttpClient() - { - } - - virtual void SetSourceCurrencyCode(Platform::String ^ sourceCurrencyCode) = 0; - virtual void SetResponseLanguage(Platform::String ^ responseLanguage) = 0; - - virtual Windows::Foundation::IAsyncOperationWithProgress ^ GetCurrencyMetadata() = 0; - virtual Windows::Foundation::IAsyncOperationWithProgress ^ GetCurrencyRatios() = 0; - }; - } -} diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj index ed1a9fb1..842c1279 100644 --- a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj @@ -319,8 +319,6 @@ - - @@ -357,7 +355,6 @@ - @@ -379,6 +376,7 @@ + @@ -391,31 +389,6 @@ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed} - - - /DUSE_MOCK_DATA %(AdditionalOptions) - stdcpp17 - stdcpp17 - stdcpp17 - stdcpp17 - stdcpp17 - stdcpp17 - stdcpp17 - stdcpp17 - - - - - - - - - - - - - - diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters index 2691d534..d2091270 100644 --- a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters @@ -177,12 +177,6 @@ DataLoaders - - DataLoaders - - - DataLoaders - DataLoaders diff --git a/src/CalcViewModelCopyForUT/DataLoaders/CurrencyHttpClient.cpp b/src/CalcViewModelCopyForUT/DataLoaders/CurrencyHttpClient.cpp new file mode 100644 index 00000000..c3be0e5d --- /dev/null +++ b/src/CalcViewModelCopyForUT/DataLoaders/CurrencyHttpClient.cpp @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "DataLoaders/CurrencyHttpClient.h" + +namespace +{ + constexpr auto MockCurrencyConverterData = + LR"([{"An":"USD","Ch":0,"Pc":0,"Rt":1},{"An":"EUR","Ch":0.003803,"Pc":0.4149,"Rt":0.920503,"Yh":0.9667,"Yl":0.86701}])"; + constexpr auto MockCurrencyStaticData = + LR"([{"CountryCode":"USA","CountryName":"United States","CurrencyCode":"USD","CurrencyName":"Dollar","CurrencySymbol":"$"},{"CountryCode":"EUR","CountryName":"Europe","CurrencyCode":"EUR","CurrencyName":"Euro","CurrencySymbol":"€"}])"; +} + +namespace CalculatorApp::ViewModel::DataLoaders +{ + bool CurrencyHttpClient::ForceWebFailure = false; + void CurrencyHttpClient::Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage) + { + m_sourceCurrencyCode = sourceCurrencyCode; + m_responseLanguage = responseLanguage; + } + + MockAwaitable CurrencyHttpClient::GetCurrencyMetadataAsync() const + { + if (ForceWebFailure) + { + throw ref new Platform::Exception(E_FAIL, L"Mocked Network Failure: failed to load currency metadata"); + } + (void)m_responseLanguage; // to be used in production. + return MockAwaitable{ ref new Platform::String(MockCurrencyStaticData) }; + } + + MockAwaitable CurrencyHttpClient::GetCurrencyRatiosAsync() const + { + if (ForceWebFailure) + { + throw ref new Platform::Exception(E_FAIL, L"Mocked Network Failure: failed to load currency metadata"); + } + (void)m_sourceCurrencyCode; // to be used in production. + return MockAwaitable{ ref new Platform::String(MockCurrencyConverterData) }; + } +} // namespace CalculatorApp::ViewModel::DataLoaders diff --git a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj index 24b78e95..39b49d58 100644 --- a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj +++ b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj @@ -207,7 +207,6 @@ - @@ -243,7 +242,6 @@ - diff --git a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters index 54a1bed4..93b36fe4 100644 --- a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters +++ b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters @@ -24,9 +24,6 @@ - - Mocks - @@ -38,9 +35,6 @@ - - Mocks - @@ -75,8 +69,5 @@ {f2987b0a-9832-46fc-b818-d5347362b3d8} - - {d3ec8922-022d-4531-8744-f65a872f3841} - \ No newline at end of file diff --git a/src/CalculatorUnitTests/CurrencyConverterUnitTests.cpp b/src/CalculatorUnitTests/CurrencyConverterUnitTests.cpp index 54f5193b..cd9f7367 100644 --- a/src/CalculatorUnitTests/CurrencyConverterUnitTests.cpp +++ b/src/CalculatorUnitTests/CurrencyConverterUnitTests.cpp @@ -14,61 +14,12 @@ using namespace CalculatorApp::ViewModel; using namespace CalculatorUnitTests; using namespace Concurrency; using namespace Platform; -using namespace std; using namespace UnitConversionManager; using namespace Windows::Foundation; using namespace Windows::Storage; using namespace Windows::Web::Http; using namespace Microsoft::VisualStudio::CppUnitTestFramework; -namespace CalculatorApp::ViewModel -{ - namespace DataLoaders - { - class MockCurrencyHttpClientWithResult : public CurrencyHttpClient - { - public: - MockCurrencyHttpClientWithResult(String ^ staticResponse, String ^ allRatiosResponse) - : m_staticResponse(staticResponse) - , m_allRatiosResponse(allRatiosResponse) - { - } - - IAsyncOperationWithProgress ^ GetCurrencyMetadata() override - { - return ref new MockAsyncOperationWithProgress(m_staticResponse); - } - - IAsyncOperationWithProgress ^ GetCurrencyRatios() override - { - return ref new MockAsyncOperationWithProgress(m_allRatiosResponse); - } - - private: - String ^ m_staticResponse; - String ^ m_allRatiosResponse; - }; - - class MockCurrencyHttpClientThrowsException : public CurrencyHttpClient - { - public: - MockCurrencyHttpClientThrowsException() - { - } - - IAsyncOperationWithProgress ^ GetCurrencyMetadata() override - { - throw ref new NotImplementedException(); - } - - IAsyncOperationWithProgress ^ GetCurrencyRatios() override - { - throw ref new NotImplementedException(); - } - }; - } -} - class DataLoadedCallback : public UnitConversionManager::IViewModelCurrencyCallback { public: @@ -82,10 +33,10 @@ public: m_task_completion_event.set(); } - void CurrencySymbolsCallback(_In_ const wstring& /*fromSymbol*/, _In_ const wstring& /*toSymbol*/) override + void CurrencySymbolsCallback(_In_ const std::wstring& /*fromSymbol*/, _In_ const std::wstring& /*toSymbol*/) override { } - void CurrencyRatiosCallback(_In_ const wstring& /*ratioEquality*/, _In_ const wstring& /*accRatioEquality*/) override + void CurrencyRatiosCallback(_In_ const std::wstring& /*ratioEquality*/, _In_ const std::wstring& /*accRatioEquality*/) override { } void CurrencyTimestampCallback(_In_ const std::wstring& /*timestamp*/, bool /*isWeekOldData*/) override @@ -101,16 +52,32 @@ private: namespace CalculatorUnitTests { - constexpr auto sc_Language_EN = L"en-US"; - - unique_ptr MakeLoaderWithResults(String ^ staticResponse, String ^ allRatiosResponse) + namespace { - auto client = make_unique(staticResponse, allRatiosResponse); - client->SetSourceCurrencyCode(StringReference(DefaultCurrencyCode.data())); - return make_unique(move(client)); + template + auto ScopeGuard(F&& f) + { + struct ScopeExit + { + explicit ScopeExit(F&& ef) + : ExitFunctor(std::forward(ef)) + { + } + ScopeExit(const ScopeExit&) = delete; + ScopeExit(ScopeExit&&) = delete; + ~ScopeExit() + { + ExitFunctor(); + } + F ExitFunctor; + }; + return ScopeExit{ std::forward(f) }; + } } - String^ SerializeContent(const vector& data) + constexpr auto sc_Language_EN = L"en-US"; + + String^ SerializeContent(const std::vector& data) { String^ result = L""; String^ delimiter = CurrencyDataLoaderConstants::CacheDelimiter; @@ -193,8 +160,8 @@ namespace CalculatorUnitTests VERIFY_IS_TRUE(DeleteCurrencyCacheFiles()); - VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient::GetRawStaticDataResponse())); - VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient::GetRawAllRatiosDataResponse())); + VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().Value)); + VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient{}.GetCurrencyRatiosAsync().Value)); } TEST_CLASS(CurrencyConverterLoadTests){ public: TEST_METHOD_INITIALIZE(DeleteCacheFiles){ DeleteCurrencyCacheFiles(); @@ -203,7 +170,7 @@ namespace CalculatorUnitTests TEST_METHOD(LoadFromCache_Fail_NoCacheKey) { RemoveFromLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; bool didLoad = loader.TryLoadDataFromCacheAsync().get(); @@ -221,7 +188,9 @@ TEST_METHOD(LoadFromCache_Fail_OlderThanADay) dayOld.UniversalTime = now.UniversalTime - CurrencyDataLoaderConstants::DayDuration - 1; InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, dayOld); - CurrencyDataLoader loader(nullptr, L"en-US"); + auto guard = ScopeGuard([] { CurrencyHttpClient::ForceWebFailure = false; }); + CurrencyHttpClient::ForceWebFailure = true; + CurrencyDataLoader loader{ L"en-US" }; bool didLoad = loader.TryLoadDataFromCacheAsync().get(); @@ -238,9 +207,9 @@ TEST_METHOD(LoadFromCache_Fail_StaticDataFileDoesNotExist) InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now); VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename)); - VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient::GetRawAllRatiosDataResponse())); + VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient{}.GetCurrencyRatiosAsync().Value)); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; bool didLoad = loader.TryLoadDataFromCacheAsync().get(); @@ -256,10 +225,10 @@ TEST_METHOD(LoadFromCache_Fail_AllRatiosDataFileDoesNotExist) DateTime now = Utils::GetUniversalSystemTime(); InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now); - VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient::GetRawStaticDataResponse())); + VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().Value)); VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename)); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; bool didLoad = loader.TryLoadDataFromCacheAsync().get(); @@ -276,10 +245,10 @@ TEST_METHOD(LoadFromCache_Fail_ResponseLanguageChanged) // Tests always use en-US as response language. Insert a different lang-code to fail the test. InsertToLocalSettings(CurrencyDataLoaderConstants::CacheLangcodeKey, L"ar-SA"); - VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient::GetRawStaticDataResponse())); + VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().Value)); VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename)); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; bool didLoad = loader.TryLoadDataFromCacheAsync().get(); @@ -292,7 +261,7 @@ TEST_METHOD(LoadFromCache_Success) { StandardCacheSetup(); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; bool didLoad = loader.TryLoadDataFromCacheAsync().get(); @@ -301,20 +270,11 @@ TEST_METHOD(LoadFromCache_Success) VERIFY_IS_TRUE(loader.LoadedFromCache()); } -TEST_METHOD(LoadFromWeb_Fail_ClientIsNullptr) -{ - CurrencyDataLoader loader(nullptr, L"en-US"); - - bool didLoad = loader.TryLoadDataFromWebAsync().get(); - - VERIFY_IS_FALSE(didLoad); - VERIFY_IS_FALSE(loader.LoadFinished()); - VERIFY_IS_FALSE(loader.LoadedFromWeb()); -} - TEST_METHOD(LoadFromWeb_Fail_WebException) { - CurrencyDataLoader loader(make_unique(), L"en-US"); + auto guard = ScopeGuard([] { CurrencyHttpClient::ForceWebFailure = false; }); + CurrencyHttpClient::ForceWebFailure = true; + CurrencyDataLoader loader{ L"en-US" }; bool didLoad = loader.TryLoadDataFromWebAsync().get(); @@ -325,24 +285,22 @@ TEST_METHOD(LoadFromWeb_Fail_WebException) TEST_METHOD(LoadFromWeb_Success) { - String ^ staticResponse = CurrencyHttpClient::GetRawStaticDataResponse(); - String ^ allRatiosResponse = CurrencyHttpClient::GetRawAllRatiosDataResponse(); - unique_ptr loader = MakeLoaderWithResults(staticResponse, allRatiosResponse); + CurrencyDataLoader loader{ L"en-US" }; - bool didLoad = loader->TryLoadDataFromWebAsync().get(); + bool didLoad = loader.TryLoadDataFromWebAsync().get(); VERIFY_IS_TRUE(didLoad); - VERIFY_IS_TRUE(loader->LoadFinished()); - VERIFY_IS_TRUE(loader->LoadedFromWeb()); + VERIFY_IS_TRUE(loader.LoadFinished()); + VERIFY_IS_TRUE(loader.LoadedFromWeb()); } TEST_METHOD(Load_Success_LoadedFromCache) { StandardCacheSetup(); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; auto data_loaded_event = task_completion_event(); - loader.SetViewModelCallback(make_shared(data_loaded_event)); + loader.SetViewModelCallback(std::make_shared(data_loaded_event)); auto data_loaded_task = create_task(data_loaded_event); loader.LoadData(); @@ -362,20 +320,18 @@ TEST_METHOD(Load_Success_LoadedFromWeb) dayOld.UniversalTime = now.UniversalTime - CurrencyDataLoaderConstants::DayDuration - 1; InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, dayOld); - String ^ staticResponse = CurrencyHttpClient::GetRawStaticDataResponse(); - String ^ allRatiosResponse = CurrencyHttpClient::GetRawAllRatiosDataResponse(); - unique_ptr loader = MakeLoaderWithResults(staticResponse, allRatiosResponse); + CurrencyDataLoader loader{ L"en-US" }; auto data_loaded_event = task_completion_event(); - loader->SetViewModelCallback(make_shared(data_loaded_event)); + loader.SetViewModelCallback(std::make_shared(data_loaded_event)); auto data_loaded_task = create_task(data_loaded_event); - loader->LoadData(); + loader.LoadData(); data_loaded_task.wait(); - VERIFY_IS_TRUE(loader->LoadFinished()); - VERIFY_IS_FALSE(loader->LoadedFromCache()); - VERIFY_IS_TRUE(loader->LoadedFromWeb()); + VERIFY_IS_TRUE(loader.LoadFinished()); + VERIFY_IS_FALSE(loader.LoadedFromCache()); + VERIFY_IS_TRUE(loader.LoadedFromWeb()); } } ; @@ -384,18 +340,18 @@ TEST_CLASS(CurrencyConverterUnitTests) { const UCM::Category CURRENCY_CATEGORY = { NavCategoryStates::Serialize(ViewMode::Currency), L"Currency", false /*supportsNegative*/ }; - const UCM::Unit GetUnit(const vector& unitList, const wstring& target) + const UCM::Unit GetUnit(const std::vector& unitList, const std::wstring& target) { - return *find_if(begin(unitList), end(unitList), [&target](const UCM::Unit& u) { return u.abbreviation == target; }); + return *std::find_if(std::begin(unitList), std::end(unitList), [&target](const UCM::Unit& u) { return u.abbreviation == target; }); } TEST_METHOD(Loaded_LoadOrderedUnits) { StandardCacheSetup(); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; auto data_loaded_event = task_completion_event(); - loader.SetViewModelCallback(make_shared(data_loaded_event)); + loader.SetViewModelCallback(std::make_shared(data_loaded_event)); auto data_loaded_task = create_task(data_loaded_event); loader.LoadData(); @@ -405,27 +361,27 @@ TEST_CLASS(CurrencyConverterUnitTests) VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_FALSE(loader.LoadedFromWeb()); - vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); + std::vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit eurUnit = GetUnit(unitList, L"EUR"); - VERIFY_ARE_EQUAL(wstring(L"United States - Dollar"), usdUnit.name); - VERIFY_ARE_EQUAL(wstring(L"USD"), usdUnit.abbreviation); + VERIFY_ARE_EQUAL(std::wstring(L"United States - Dollar"), usdUnit.name); + VERIFY_ARE_EQUAL(std::wstring(L"USD"), usdUnit.abbreviation); - VERIFY_ARE_EQUAL(wstring(L"Europe - Euro"), eurUnit.name); - VERIFY_ARE_EQUAL(wstring(L"EUR"), eurUnit.abbreviation); + VERIFY_ARE_EQUAL(std::wstring(L"Europe - Euro"), eurUnit.name); + VERIFY_ARE_EQUAL(std::wstring(L"EUR"), eurUnit.abbreviation); } TEST_METHOD(Loaded_LoadOrderedRatios) { StandardCacheSetup(); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; auto data_loaded_event = task_completion_event(); - loader.SetViewModelCallback(make_shared(data_loaded_event)); + loader.SetViewModelCallback(std::make_shared(data_loaded_event)); auto data_loaded_task = create_task(data_loaded_event); loader.LoadData(); @@ -435,13 +391,13 @@ TEST_CLASS(CurrencyConverterUnitTests) VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_FALSE(loader.LoadedFromWeb()); - vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); + std::vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit eurUnit = GetUnit(unitList, L"EUR"); - unordered_map ratios = loader.LoadOrderedRatios(usdUnit); + std::unordered_map ratios = loader.LoadOrderedRatios(usdUnit); VERIFY_ARE_EQUAL(size_t{ 2 }, ratios.size()); UCM::ConversionData usdRatioData = ratios[usdUnit]; @@ -455,10 +411,10 @@ TEST_CLASS(CurrencyConverterUnitTests) { StandardCacheSetup(); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; auto data_loaded_event = task_completion_event(); - loader.SetViewModelCallback(make_shared(data_loaded_event)); + loader.SetViewModelCallback(std::make_shared(data_loaded_event)); auto data_loaded_task = create_task(data_loaded_event); loader.LoadData(); @@ -468,26 +424,26 @@ TEST_CLASS(CurrencyConverterUnitTests) VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_FALSE(loader.LoadedFromWeb()); - vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); + std::vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit eurUnit = GetUnit(unitList, L"EUR"); - const pair symbols = loader.GetCurrencySymbols(usdUnit, eurUnit); + const auto symbols = loader.GetCurrencySymbols(usdUnit, eurUnit); - VERIFY_ARE_EQUAL(wstring(L"$"), symbols.first); - VERIFY_ARE_EQUAL(wstring(L"\x20ac"), symbols.second); // € + VERIFY_ARE_EQUAL(std::wstring(L"$"), symbols.first); + VERIFY_ARE_EQUAL(std::wstring(L"\x20ac"), symbols.second); // € } TEST_METHOD(Loaded_GetCurrencySymbols_Invalid) { StandardCacheSetup(); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; auto data_loaded_event = task_completion_event(); - loader.SetViewModelCallback(make_shared(data_loaded_event)); + loader.SetViewModelCallback(std::make_shared(data_loaded_event)); auto data_loaded_task = create_task(data_loaded_event); loader.LoadData(); @@ -501,36 +457,36 @@ TEST_CLASS(CurrencyConverterUnitTests) const UCM::Unit fakeUnit2 = { 2, L"fakeUnit2", L"FUD2", false, false, false }; - pair symbols = loader.GetCurrencySymbols(fakeUnit1, fakeUnit2); + auto symbols = loader.GetCurrencySymbols(fakeUnit1, fakeUnit2); - VERIFY_ARE_EQUAL(wstring(L""), wstring(symbols.first.c_str())); - VERIFY_ARE_EQUAL(wstring(L""), wstring(symbols.second.c_str())); + VERIFY_ARE_EQUAL(std::wstring(L""), std::wstring(symbols.first.c_str())); + VERIFY_ARE_EQUAL(std::wstring(L""), std::wstring(symbols.second.c_str())); // Verify that when only one unit is valid, both symbols return as empty string. - vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); + std::vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); symbols = loader.GetCurrencySymbols(fakeUnit1, usdUnit); - VERIFY_ARE_EQUAL(wstring(L""), symbols.first); - VERIFY_ARE_EQUAL(wstring(L""), symbols.second); + VERIFY_ARE_EQUAL(std::wstring(L""), symbols.first); + VERIFY_ARE_EQUAL(std::wstring(L""), symbols.second); symbols = loader.GetCurrencySymbols(usdUnit, fakeUnit1); - VERIFY_ARE_EQUAL(wstring(L""), symbols.first); - VERIFY_ARE_EQUAL(wstring(L""), symbols.second); + VERIFY_ARE_EQUAL(std::wstring(L""), symbols.first); + VERIFY_ARE_EQUAL(std::wstring(L""), symbols.second); } TEST_METHOD(Loaded_GetCurrencyRatioEquality_Valid) { StandardCacheSetup(); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; auto data_loaded_event = task_completion_event(); - loader.SetViewModelCallback(make_shared(data_loaded_event)); + loader.SetViewModelCallback(std::make_shared(data_loaded_event)); auto data_loaded_task = create_task(data_loaded_event); loader.LoadData(); @@ -540,26 +496,26 @@ TEST_CLASS(CurrencyConverterUnitTests) VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_FALSE(loader.LoadedFromWeb()); - vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); + std::vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit eurUnit = GetUnit(unitList, L"EUR"); - const pair ratio = loader.GetCurrencyRatioEquality(usdUnit, eurUnit); + const auto ratio = loader.GetCurrencyRatioEquality(usdUnit, eurUnit); - VERIFY_ARE_EQUAL(wstring(L"1 USD = 0.9205 EUR"), ratio.first); - VERIFY_ARE_EQUAL(wstring(L"1 United States Dollar = 0.9205 Europe Euro"), ratio.second); + VERIFY_ARE_EQUAL(std::wstring(L"1 USD = 0.9205 EUR"), ratio.first); + VERIFY_ARE_EQUAL(std::wstring(L"1 United States Dollar = 0.9205 Europe Euro"), ratio.second); } TEST_METHOD(Loaded_GetCurrencyRatioEquality_Invalid) { StandardCacheSetup(); - CurrencyDataLoader loader(nullptr, L"en-US"); + CurrencyDataLoader loader{ L"en-US" }; auto data_loaded_event = task_completion_event(); - loader.SetViewModelCallback(make_shared(data_loaded_event)); + loader.SetViewModelCallback(std::make_shared(data_loaded_event)); auto data_loaded_task = create_task(data_loaded_event); loader.LoadData(); @@ -572,26 +528,26 @@ TEST_CLASS(CurrencyConverterUnitTests) const UCM::Unit fakeUnit1 = { 1, L"fakeUnit1", L"fakeCountry1", L"FUD1", false, false, false }; const UCM::Unit fakeUnit2 = { 2, L"fakeUnit2", L"fakeCountry2", L"FUD2", false, false, false }; - pair ratio = loader.GetCurrencyRatioEquality(fakeUnit1, fakeUnit2); + auto ratio = loader.GetCurrencyRatioEquality(fakeUnit1, fakeUnit2); - VERIFY_ARE_EQUAL(wstring(L""), ratio.first); - VERIFY_ARE_EQUAL(wstring(L""), ratio.second); + VERIFY_ARE_EQUAL(std::wstring(L""), ratio.first); + VERIFY_ARE_EQUAL(std::wstring(L""), ratio.second); // Verify that when only one unit is valid, both symbols return as empty string. - vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); + std::vector unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); ratio = loader.GetCurrencyRatioEquality(fakeUnit1, usdUnit); - VERIFY_ARE_EQUAL(wstring(L""), ratio.first); - VERIFY_ARE_EQUAL(wstring(L""), ratio.second); + VERIFY_ARE_EQUAL(std::wstring(L""), ratio.first); + VERIFY_ARE_EQUAL(std::wstring(L""), ratio.second); ratio = loader.GetCurrencyRatioEquality(usdUnit, fakeUnit1); - VERIFY_ARE_EQUAL(wstring(L""), ratio.first); - VERIFY_ARE_EQUAL(wstring(L""), ratio.second); + VERIFY_ARE_EQUAL(std::wstring(L""), ratio.first); + VERIFY_ARE_EQUAL(std::wstring(L""), ratio.second); } TEST_METHOD(Test_RoundCurrencyRatio) diff --git a/src/CalculatorUnitTests/Mocks/CurrencyHttpClient.cpp b/src/CalculatorUnitTests/Mocks/CurrencyHttpClient.cpp deleted file mode 100644 index 975a3388..00000000 --- a/src/CalculatorUnitTests/Mocks/CurrencyHttpClient.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "CurrencyHttpClient.h" - -#include "CalcViewModel/Common/NetworkManager.h" - -using namespace CalculatorApp::ViewModel::DataLoaders; -using namespace Platform; -using namespace Windows::Foundation; -using namespace Windows::System::UserProfile; -using namespace Windows::Web::Http; - -// Generic responses so unit tests will pass. -static constexpr auto STATIC_DATA_RESPONSE = - LR"([{"CountryCode":"USA","CountryName":"United States","CurrencyCode":"USD","CurrencyName":"Dollar","CurrencySymbol":"$"},{"CountryCode":"EUR","CountryName":"Europe","CurrencyCode":"EUR","CurrencyName":"Euro","CurrencySymbol":"€"}])"; -static constexpr auto ALL_RATIOS_RESPONSE = - LR"([{"An":"USD","Ch":0,"Pc":0,"Rt":1},{"An":"EUR","Ch":0.003803,"Pc":0.4149,"Rt":0.920503,"Yh":0.9667,"Yl":0.86701}])"; - -CurrencyHttpClient::CurrencyHttpClient() -{ -} - -String ^ CurrencyHttpClient::GetRawStaticDataResponse() -{ - return StringReference(STATIC_DATA_RESPONSE); -} - -String ^ CurrencyHttpClient::GetRawAllRatiosDataResponse() -{ - return StringReference(ALL_RATIOS_RESPONSE); -} - -IAsyncOperationWithProgress ^ CurrencyHttpClient::GetCurrencyMetadata() -{ - return ref new MockAsyncOperationWithProgress(StringReference(STATIC_DATA_RESPONSE)); -} - -IAsyncOperationWithProgress ^ CurrencyHttpClient::GetCurrencyRatios() -{ - return ref new MockAsyncOperationWithProgress(StringReference(ALL_RATIOS_RESPONSE)); -} - -MockAsyncOperationWithProgress::MockAsyncOperationWithProgress(String ^ result) - : m_result(result) -{ -} - -HResult MockAsyncOperationWithProgress::ErrorCode::get() -{ - HResult okayResult; - okayResult.Value = S_OK; - return okayResult; -} diff --git a/src/CalculatorUnitTests/Mocks/CurrencyHttpClient.h b/src/CalculatorUnitTests/Mocks/CurrencyHttpClient.h deleted file mode 100644 index ec88217a..00000000 --- a/src/CalculatorUnitTests/Mocks/CurrencyHttpClient.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "CalcViewModel/DataLoaders/ICurrencyHttpClient.h" - -namespace CalculatorApp::ViewModel -{ - namespace DataLoaders - { - class CurrencyHttpClient : public ICurrencyHttpClient - { - public: - CurrencyHttpClient(); - - static Platform::String ^ GetRawStaticDataResponse(); - static Platform::String ^ GetRawAllRatiosDataResponse(); - - // ICurrencyHttpClient - void SetSourceCurrencyCode(Platform::String ^ sourceCurrencyCode) override - { - } - void SetResponseLanguage(Platform::String ^ responseLanguage) override - { - } - - virtual Windows::Foundation::IAsyncOperationWithProgress ^ GetCurrencyMetadata() override; - virtual Windows::Foundation::IAsyncOperationWithProgress ^ GetCurrencyRatios() override; - // ICurrencyHttpClient - }; - - public - ref class MockAsyncOperationWithProgress sealed - : public Windows::Foundation::IAsyncOperationWithProgress - { - public: - MockAsyncOperationWithProgress(Platform::String ^ result); - - // IAsyncInfo - virtual property Windows::Foundation::HResult ErrorCode - { - Windows::Foundation::HResult get(); - } - - virtual property unsigned int Id - { - unsigned int get() - { - return 128u; - } - } - - virtual property Windows::Foundation::AsyncStatus Status - { - Windows::Foundation::AsyncStatus get() - { - return Windows::Foundation::AsyncStatus::Completed; - } - } - - virtual void Cancel() - { - } - virtual void Close() - { - } - // IAsyncInfo - - // IAsyncOperationWithProgress - virtual property Windows::Foundation::AsyncOperationProgressHandler^ Progress - { - Windows::Foundation::AsyncOperationProgressHandler^ get() { return nullptr; } - void set(Windows::Foundation::AsyncOperationProgressHandler^ handler) {} - } - - virtual property Windows::Foundation::AsyncOperationWithProgressCompletedHandler^ Completed - { - Windows::Foundation::AsyncOperationWithProgressCompletedHandler^ get() { return nullptr; } - void set(Windows::Foundation::AsyncOperationWithProgressCompletedHandler^ handler) {} - } - - virtual Platform::String^ GetResults() { return m_result; } - // IAsyncOperationWithProgress - - private: - Platform::String^ m_result; - }; - } -} diff --git a/src/CalculatorUnitTests/pch.h b/src/CalculatorUnitTests/pch.h index e24dd530..11404e90 100644 --- a/src/CalculatorUnitTests/pch.h +++ b/src/CalculatorUnitTests/pch.h @@ -62,7 +62,6 @@ #include "CalcViewModel/Common/CalculatorButtonUser.h" #include "CalcViewModel/Common/NetworkManager.h" -#include "Mocks/CurrencyHttpClient.h" #include "Helpers.h" #include "UnitTestApp.xaml.h"