replace mocked awaitable with std future

This commit is contained in:
Tian Liao 2024-11-28 18:22:02 +08:00
commit 03175a2bb8
6 changed files with 43 additions and 37 deletions

View file

@ -127,22 +127,25 @@ 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;
m_responseLanguage = responseLanguage; m_responseLanguage = responseLanguage;
} }
MockAwaitable<Platform::String ^> CurrencyHttpClient::GetCurrencyMetadataAsync() const std::future<Platform::String ^> CurrencyHttpClient::GetCurrencyMetadataAsync() const
{ {
(void)m_responseLanguage; // to be used in production. (void)m_responseLanguage; // to be used in production.
return MockAwaitable<Platform::String ^>{ ref new Platform::String(MockCurrencyStaticData) }; std::promise<Platform::String ^> mockedTask;
mockedTask.set_value(ref new Platform::String(MockCurrencyStaticData));
return mockedTask.get_future();
} }
MockAwaitable<Platform::String ^> CurrencyHttpClient::GetCurrencyRatiosAsync() const std::future<Platform::String ^> CurrencyHttpClient::GetCurrencyRatiosAsync() const
{ {
(void)m_sourceCurrencyCode; // to be used in production. (void)m_sourceCurrencyCode; // to be used in production.
return MockAwaitable<Platform::String ^>{ ref new Platform::String(MockCurrencyConverterData) }; std::promise<Platform::String ^> mockedTask;
mockedTask.set_value(ref new Platform::String(MockCurrencyConverterData));
return mockedTask.get_future();
} }
} // namespace CalculatorApp::ViewModel::DataLoaders } // namespace CalculatorApp::ViewModel::DataLoaders

View file

@ -3,38 +3,20 @@
#pragma once #pragma once
#include <cassert> #include <cassert>
#include <future>
namespace CalculatorApp::ViewModel::DataLoaders namespace CalculatorApp::ViewModel::DataLoaders
{ {
template <class T>
struct MockAwaitable
{
T Value;
bool await_ready() const noexcept
{
return true;
}
void await_suspend(std::experimental::coroutine_handle<>) const noexcept
{
assert(false && "not implemented.");
}
T await_resume() noexcept
{
return std::move(Value);
}
};
class CurrencyHttpClient class CurrencyHttpClient
{ {
public: public:
#ifdef VIEWMODEL_FOR_UT
static bool ForceWebFailure; static bool ForceWebFailure;
#endif
void Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage); void Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage);
MockAwaitable<Platform::String ^> GetCurrencyMetadataAsync() const; std::future<Platform::String ^> GetCurrencyMetadataAsync() const;
MockAwaitable<Platform::String ^> GetCurrencyRatiosAsync() const; std::future<Platform::String ^> GetCurrencyRatiosAsync() const;
private: private:
Platform::String ^ m_sourceCurrencyCode; Platform::String ^ m_sourceCurrencyCode;

View file

@ -136,6 +136,7 @@
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -156,6 +157,7 @@
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -176,6 +178,7 @@
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -196,6 +199,7 @@
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -216,6 +220,7 @@
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -236,6 +241,7 @@
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -256,6 +262,7 @@
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -276,6 +283,7 @@
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>

View file

@ -21,23 +21,28 @@ namespace CalculatorApp::ViewModel::DataLoaders
m_responseLanguage = responseLanguage; m_responseLanguage = responseLanguage;
} }
MockAwaitable<Platform::String ^> CurrencyHttpClient::GetCurrencyMetadataAsync() const std::future<Platform::String ^> CurrencyHttpClient::GetCurrencyMetadataAsync() const
{ {
if (ForceWebFailure) if (ForceWebFailure)
{ {
throw ref new Platform::Exception(E_FAIL, L"Mocked Network Failure: failed to load currency metadata"); 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 MockAwaitable<Platform::String ^>{ ref new Platform::String(MockCurrencyStaticData) }; std::promise<Platform::String ^> mockedTask;
mockedTask.set_value(ref new Platform::String(MockCurrencyStaticData));
return mockedTask.get_future();
} }
MockAwaitable<Platform::String ^> CurrencyHttpClient::GetCurrencyRatiosAsync() const std::future<Platform::String ^> CurrencyHttpClient::GetCurrencyRatiosAsync() const
{ {
if (ForceWebFailure) if (ForceWebFailure)
{ {
throw ref new Platform::Exception(E_FAIL, L"Mocked Network Failure: failed to load currency metadata"); 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 MockAwaitable<Platform::String ^>{ ref new Platform::String(MockCurrencyConverterData) };
std::promise<Platform::String ^> mockedTask;
mockedTask.set_value(ref new Platform::String(MockCurrencyConverterData));
return mockedTask.get_future();
} }
} // namespace CalculatorApp::ViewModel::DataLoaders } // namespace CalculatorApp::ViewModel::DataLoaders

View file

@ -135,6 +135,7 @@
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)CalcManager;$(SolutionDir)CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)CalcManager;$(SolutionDir)CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
@ -145,6 +146,7 @@
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<ControlFlowGuard>Guard</ControlFlowGuard> <ControlFlowGuard>Guard</ControlFlowGuard>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
@ -154,6 +156,7 @@
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)CalcManager;$(SolutionDir)CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)CalcManager;$(SolutionDir)CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
@ -164,6 +167,7 @@
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<ControlFlowGuard>Guard</ControlFlowGuard> <ControlFlowGuard>Guard</ControlFlowGuard>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -173,6 +177,7 @@
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)CalcManager;$(SolutionDir)CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)CalcManager;$(SolutionDir)CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -183,6 +188,7 @@
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<ControlFlowGuard>Guard</ControlFlowGuard> <ControlFlowGuard>Guard</ControlFlowGuard>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -192,6 +198,7 @@
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)CalcManager;$(SolutionDir)CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)CalcManager;$(SolutionDir)CalcViewModel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -202,6 +209,7 @@
<WarningLevel>Level4</WarningLevel> <WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<ControlFlowGuard>Guard</ControlFlowGuard> <ControlFlowGuard>Guard</ControlFlowGuard>
<PreprocessorDefinitions>VIEWMODEL_FOR_UT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View file

@ -160,8 +160,8 @@ namespace CalculatorUnitTests
VERIFY_IS_TRUE(DeleteCurrencyCacheFiles()); VERIFY_IS_TRUE(DeleteCurrencyCacheFiles());
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().Value)); VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().get()));
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient{}.GetCurrencyRatiosAsync().Value)); VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient{}.GetCurrencyRatiosAsync().get()));
} }
TEST_CLASS(CurrencyConverterLoadTests){ public: TEST_METHOD_INITIALIZE(DeleteCacheFiles){ DeleteCurrencyCacheFiles(); TEST_CLASS(CurrencyConverterLoadTests){ public: TEST_METHOD_INITIALIZE(DeleteCacheFiles){ DeleteCurrencyCacheFiles();
@ -207,7 +207,7 @@ TEST_METHOD(LoadFromCache_Fail_StaticDataFileDoesNotExist)
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now); InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now);
VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename)); VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename));
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient{}.GetCurrencyRatiosAsync().Value)); VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename, CurrencyHttpClient{}.GetCurrencyRatiosAsync().get()));
CurrencyDataLoader loader{ L"en-US" }; CurrencyDataLoader loader{ L"en-US" };
@ -225,7 +225,7 @@ TEST_METHOD(LoadFromCache_Fail_AllRatiosDataFileDoesNotExist)
DateTime now = Utils::GetUniversalSystemTime(); DateTime now = Utils::GetUniversalSystemTime();
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now); InsertToLocalSettings(CurrencyDataLoaderConstants::CacheTimestampKey, now);
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().Value)); VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().get()));
VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename)); VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename));
CurrencyDataLoader loader{ L"en-US" }; CurrencyDataLoader loader{ L"en-US" };
@ -245,7 +245,7 @@ TEST_METHOD(LoadFromCache_Fail_ResponseLanguageChanged)
// Tests always use en-US as response language. Insert a different lang-code to fail the test. // Tests always use en-US as response language. Insert a different lang-code to fail the test.
InsertToLocalSettings(CurrencyDataLoaderConstants::CacheLangcodeKey, L"ar-SA"); InsertToLocalSettings(CurrencyDataLoaderConstants::CacheLangcodeKey, L"ar-SA");
VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().Value)); VERIFY_IS_TRUE(WriteToFileInLocalCacheFolder(CurrencyDataLoaderConstants::StaticDataFilename, CurrencyHttpClient{}.GetCurrencyMetadataAsync().get()));
VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename)); VERIFY_IS_TRUE(DeleteFileFromLocalCacheFolder(CurrencyDataLoaderConstants::AllRatiosDataFilename));
CurrencyDataLoader loader{ L"en-US" }; CurrencyDataLoader loader{ L"en-US" };