I am working a project that puts a gui interface to a 3rd party database backup utility. This is my first project I have done where I am writing unit tests. I have been writing almost the entire project using TDD methodology up until now, but I got stumped with this function and just wrote it without TDD. Going back I still don't know how to test it.
private void ValidateCustomDbPath()
{
if (_validateCustomDbPathTask != null && !_validateCustomDbPathTask.IsCompleted)
{
_validateCustomDbPathCancellationTokenSource.Cancel();
}
if (string.IsNullOrEmpty(_customDbPath))
{
Set(() => CustomDbPathValidation, ref _customDbPathValidation, ValidationState.Validated);
Set(() => CustomDbPathValidationMessage, ref _customDbPathValidationMessage, "");
_customDbPathCompany = string.Empty;
UpdateDefaultBackupPath();
return;
}
_validateCustomDbPathCancellationTokenSource = new CancellationTokenSource();
var ct = _validateCustomDbPathCancellationTokenSource.Token;
_validateCustomDbPathTask = Task.Run(async () =>
{
Set(() => CustomDbPathValidation, ref _customDbPathValidation, ValidationState.Validating);
Set(() => CustomDbPathValidationMessage, ref _customDbPathValidationMessage, "");
try
{
if (!_diskUtils.File.Exists(_customDbPath))
{
Set(() => CustomDbPathValidation, ref _customDbPathValidation, ValidationState.Invalid);
Set(() => CustomDbPathValidationMessage, ref _customDbPathValidationMessage, "File not found");
_customDbPathCompany = string.Empty;
UpdateDefaultBackupPath();
return;
}
using (var conn = _connectionProvider.GetConnection(_customDbPath, false))
using (var trxn = conn.BeginTransaction())
{
var dbSetup = await _dbSetupRepo.GetAsync(conn, trxn);
_customDbPathCompany = dbSetup.Company;
Set(() => CustomDbPathValidation, ref _customDbPathValidation, ValidationState.Validated);
Set(() => CustomDbPathValidationMessage, ref _customDbPathValidationMessage, "");
UpdateDefaultBackupPath();
}
}
catch
{
Set(() => CustomDbPathValidation, ref _customDbPathValidation, ValidationState.Invalid);
Set(() => CustomDbPathValidationMessage, ref _customDbPathValidationMessage, "Error getting company");
_customDbPathCompany = string.Empty;
UpdateDefaultBackupPath();
}
}, ct);
}
This method is in a ViewModel for a screen. It gets called in the CustomDbPath property setter after a new value is set. The idea is that I have visual indicators in the gui to show if the path provided is valid and UpdateDefaultBackupPath method updates the suggested backup file name based on information in the selected database.
Explaining what you are seeing here, the first IF block cancels the validation task if one was already running and not finished (I know I have yet to make use of the cancellation token). In the second block if no path is provided (the starting state) I don't want to show an error and no need to validate further. In the task, I first indicate that the field is being validated, then I check if the database file can be found on disk, and finally if found I look for information in the database to be used in naming of the backup file name. I am using MVVM Light which is where the Set method comes from (it implements INotifyPropertyChanged).
Everywhere else so far where I have used tasks I have not had a problem testing. I await the method in question and test the results. This case is different. This is called in property setter which obviously can't follow the async await pattern and I wouldn't want it to anyway since it is possible for the user to change the property again before the first validation sequence has finished. The main things I am interested in testing are CustomDbPathValidation and CustomDbPathValidationMessage values. Did it set to validating before validation. Did it set to validated when it succeeded or invalid when it failed. I am more than happy to rewrite this method in a way that makes it testable I just don't know how. Any ideas?
Aucun commentaire:
Enregistrer un commentaire