mock web failures

This commit is contained in:
Tian Liao 2024-11-27 13:47:53 +08:00
commit bc880f06bc
5 changed files with 38 additions and 14 deletions

View file

@ -127,6 +127,7 @@ namespace
namespace CalculatorApp::ViewModel::DataLoaders namespace CalculatorApp::ViewModel::DataLoaders
{ {
bool CurrencyHttpClient::ForceWebFailure = false;
void CurrencyHttpClient::Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage) void CurrencyHttpClient::Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage)
{ {
m_sourceCurrencyCode = sourceCurrencyCode; m_sourceCurrencyCode = sourceCurrencyCode;

View file

@ -8,6 +8,7 @@ namespace CalculatorApp::ViewModel::DataLoaders
class CurrencyHttpClient class CurrencyHttpClient
{ {
public: public:
static bool ForceWebFailure;
void Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage); void Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage);
Platform::String ^ GetCurrencyMetadata() const; Platform::String ^ GetCurrencyMetadata() const;

View file

@ -319,7 +319,6 @@
<ClInclude Include="..\CalcViewModel\Common\TraceLogger.h" /> <ClInclude Include="..\CalcViewModel\Common\TraceLogger.h" />
<ClInclude Include="..\CalcViewModel\Common\Utils.h" /> <ClInclude Include="..\CalcViewModel\Common\Utils.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyDataLoader.h" /> <ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyDataLoader.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyHttpClient.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataConstants.h" /> <ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataConstants.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataLoader.h" /> <ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataLoader.h" />
<ClInclude Include="..\CalcViewModel\DateCalculatorViewModel.h" /> <ClInclude Include="..\CalcViewModel\DateCalculatorViewModel.h" />
@ -377,7 +376,7 @@
<ClCompile Include="..\CalcViewModel\Snapshots.cpp" /> <ClCompile Include="..\CalcViewModel\Snapshots.cpp" />
<ClCompile Include="..\CalcViewModel\StandardCalculatorViewModel.cpp" /> <ClCompile Include="..\CalcViewModel\StandardCalculatorViewModel.cpp" />
<ClCompile Include="..\CalcViewModel\UnitConverterViewModel.cpp" /> <ClCompile Include="..\CalcViewModel\UnitConverterViewModel.cpp" />
<ClCompile Include="CurrencyHttpClient.cpp" /> <ClCompile Include="DataLoaders\CurrencyHttpClient.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\CalcManager\CalcManager.vcxproj"> <ProjectReference Include="..\CalcManager\CalcManager.vcxproj">

View file

@ -2,7 +2,7 @@
// Licensed under the MIT License. // Licensed under the MIT License.
#include "pch.h" #include "pch.h"
#include "CalcViewModel/DataLoaders/CurrencyHttpClient.h" #include "DataLoaders/CurrencyHttpClient.h"
namespace namespace
{ {
@ -14,6 +14,7 @@ namespace
namespace CalculatorApp::ViewModel::DataLoaders namespace CalculatorApp::ViewModel::DataLoaders
{ {
bool CurrencyHttpClient::ForceWebFailure = false;
void CurrencyHttpClient::Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage) void CurrencyHttpClient::Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage)
{ {
m_sourceCurrencyCode = sourceCurrencyCode; m_sourceCurrencyCode = sourceCurrencyCode;
@ -22,12 +23,20 @@ namespace CalculatorApp::ViewModel::DataLoaders
Platform::String ^ CurrencyHttpClient::GetCurrencyMetadata() const Platform::String ^ CurrencyHttpClient::GetCurrencyMetadata() 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. (void)m_responseLanguage; // to be used in production.
return ref new Platform::String(MockCurrencyStaticData); return ref new Platform::String(MockCurrencyStaticData);
} }
Platform::String ^ CurrencyHttpClient::GetCurrencyRatios() const Platform::String ^ CurrencyHttpClient::GetCurrencyRatios() 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. (void)m_sourceCurrencyCode; // to be used in production.
return ref new Platform::String(MockCurrencyConverterData); return ref new Platform::String(MockCurrencyConverterData);
} }

View file

@ -52,6 +52,27 @@ private:
namespace CalculatorUnitTests namespace CalculatorUnitTests
{ {
namespace
{
template <class F>
auto ScopeGuard(F&& f)
{
struct ScopeExit
{
explicit ScopeExit(F&& ef)
: ExitFunctor(std::forward<F>(ef))
{
}
~ScopeExit()
{
ExitFunctor();
}
F ExitFunctor;
};
return ScopeExit{ std::forward<F>(f) };
}
}
constexpr auto sc_Language_EN = L"en-US"; constexpr auto sc_Language_EN = L"en-US";
String^ SerializeContent(const std::vector<String^>& data) String^ SerializeContent(const std::vector<String^>& data)
@ -165,6 +186,8 @@ TEST_METHOD(LoadFromCache_Fail_OlderThanADay)
dayOld.UniversalTime = now.UniversalTime - CurrencyDataLoaderConstants::DayDuration - 1; dayOld.UniversalTime = now.UniversalTime - CurrencyDataLoaderConstants::DayDuration - 1;
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, dayOld); InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, dayOld);
auto guard = ScopeGuard([] { CurrencyHttpClient::ForceWebFailure = false; });
CurrencyHttpClient::ForceWebFailure = true;
CurrencyDataLoader loader{ L"en-US" }; CurrencyDataLoader loader{ L"en-US" };
bool didLoad = loader.TryLoadDataFromCacheAsync().get(); bool didLoad = loader.TryLoadDataFromCacheAsync().get();
@ -245,19 +268,10 @@ TEST_METHOD(LoadFromCache_Success)
VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_TRUE(loader.LoadedFromCache());
} }
TEST_METHOD(LoadFromWeb_Fail_ClientIsNullptr)
{
CurrencyDataLoader loader{ 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) TEST_METHOD(LoadFromWeb_Fail_WebException)
{ {
auto guard = ScopeGuard([] { CurrencyHttpClient::ForceWebFailure = false; });
CurrencyHttpClient::ForceWebFailure = true;
CurrencyDataLoader loader{ L"en-US" }; CurrencyDataLoader loader{ L"en-US" };
bool didLoad = loader.TryLoadDataFromWebAsync().get(); bool didLoad = loader.TryLoadDataFromWebAsync().get();