I am unit testing a new Win8 Store app and noticed a race condition I want to avoid. So I am looking for a way to avoid this race condition.
I have a class that when instantiated calls a method to be sure it has a local StorageFolder. My unit test simply instantiates the object and tests if the folder is there. Sometime the folder is not and sometimes it is so I believe this to be a race condition because the CreateFolderAsync is asynchronous (obviously).
public class Class1
{
StorageFolder _localFolder = null;
public Class1()
{
_localFolder = ApplicationData.Current.LocalFolder;
_setUpStorageFolders();
}
public StorageFolder _LocalFolder
{
get
{
return _localFolder;
}
}
async void _setUpStorageFolders()
{
try
{
_localFolder = await _localFolder.CreateFolderAsync("TestFolder", CreationCollisionOption.FailIfExists);
}
catch (Exception)
{
throw;
}
}
}
My Unit Test Looks Like This:
[TestMethod]
public void _LocalFolder_Test()
{
Class1 ke = new Class1();
// TODO: Fix Race Condition
StorageFolder folder = ke._LocalFolder;
string folderName = folder.Name;
Assert.IsTrue(folderName == "TestFolder");
}
As Iboshuizen suggested, I would do this synchronously. This can be done with async
, task
, and await
. There is a gotcha - the setup cannot be done inside the constructor of Class1
because constructors do not support async/ await. Because of this SetUpStorageFolders
is now public, and is called from the test method.
public class Class1
{
StorageFolder _localFolder = null;
public Class1()
{
_localFolder = ApplicationData.Current.LocalFolder;
// call to setup removed here because constructors
// do not support async/ await keywords
}
public StorageFolder _LocalFolder
{
get
{
return _localFolder;
}
}
// now public... (note Task return type)
async public Task SetUpStorageFolders()
{
try
{
_localFolder = await _localFolder.CreateFolderAsync("TestFolder", CreationCollisionOption.FailIfExists);
}
catch (Exception)
{
throw;
}
}
}
Test:
// note the signature change here (async + Task)
[TestMethod]
async public Task _LocalFolder_Test()
{
Class1 ke = new Class1();
// synchronous call to SetupStorageFolders - note the await
await ke.SetUpStorageFolders();
StorageFolder folder = ke._LocalFolder;
string folderName = folder.Name;
Assert.IsTrue(folderName == "TestFolder");
}