I'm working in WinRt calling a WinRt Class Library from a Windows Store App using C# and SQLite... objects are returning null reference errors at unexpected times...
I'm trying to implement a logon service that checks to see if the current user is already logged in by checking if the data file exists, then checking if the user is the current user logged in...
The user can simply enter their ID and click a logon button. It creates a DataService object that wraps a SQLite database and is then "injected" into the UserStartupService.
The UserStartupService uses Dependency Injection, singleton and implements IDisposable.
Issue 1) if the user clicks the logon button a second time, the UserStartupService object constructor does not run and when internal objects are used they throw null reference errors even though it runs through the dispose method after it exits the using block, which forces me to deactivate the logon button, which is a kluge fix at best. A new user has to exit the program to log in as a new user. (The original code did not implement IAsyncOperationWithProgress, but that should not matter...)
Issue 2) I'm now trying to implement IAsyncOperationWithProgress to relay progress back to the UI and it gets a null reference error the instant it tries to use _dataFeedService on the line:
var json = await _dataFeedService.ValidateUser(userId);
Even though it runs the constructor at the top of the using statement as expected...
I think there is a scope/thread issue that I'm missing here. Maybe something obvious...
Any ideas? Thanks!
// logon button pressed...
private void LogOn_Click(object sender, RoutedEventArgs e)
{
// Create database service for DI
DataService _dataService = new DataService("MyData.sqlite");
// using statement for scope control
using (UserStartupService uss = UserStartupService.GetInstance(_dataService))
{
// progress bar...
CurrentProgress.Visibility = Windows.UI.Xaml.Visibility.Visible;
// create op and call...
IAsyncOperationWithProgress<string, int> op;
op = uss.SetUpUser(txtUserId.Text);
op.Progress = (info, progress) =>
{
CurrentProgress.Value = progress;
};
op.Completed = (info, status) =>
{
var results = info.GetResults();
// when completed...
if (status == AsyncStatus.Completed)
{
txtMessage.Text = "Current user data already loaded...";
CurrentProgress.Value = 100;
} // if cancelled...
else if (status == AsyncStatus.Canceled)
{
// Operation canceled - not implemented...
}
};
}
btnLogon.IsEnabled = false;
}
public sealed class UserStartupService : IDisposable
{
#region properties
// services
private static DataService _dataService;
private static DataFeedService _dataFeedService;
private static SqliteService _sqlMAFService;
private static SerialiseDeserialiseService _serializeService;
private string _token = String.Empty;
#endregion properties
#region constructors with DI and singleton pattern
// use this code to implement singleton patter...
// private constructor = can't instance without GetInstance...
private UserStartupService(DataService dataService)
{
// guard clause...
if (dataService == null)
{
throw new ArgumentNullException("DataService");
}
_dataService = dataService;
_dataFeedService = new DataFeedService();
_sqlMAFService = new SqliteService(_dataService);
_serializeService = new SerialiseDeserialiseService();
}
// implement singleton
public static UserStartupService GetInstance(DataService dataService)
{
_dataService = dataService;
return MyNestedSingletonClass.singleton;
}
class MyNestedSingletonClass
{
internal static readonly UserStartupService singleton = new UserStartupService(_dataService);
static MyNestedSingletonClass() { }
}
#endregion constructors with DI and singleton pattern
public IAsyncOperationWithProgress<string, int> SetUpUser(string userId)
{
return AsyncInfo.Run<string, int>((token, progress) =>
Task.Run<string>(async () =>
{
progress.Report(1);
try
{
// validate user against server REST feed and get token
var json = await _dataFeedService.ValidateUser(userId);
// ... it never gets here due to _dataFeedService null exception
// ...more code ... never gets here...
}
catch (Exception ex)
{
return ex.Message;
}
progress.Report(100);
return "";
}, token));
}
#region implement IDisposable
public void Dispose()
{
_serializeService = null;
_sqlMAFService.Dispose();
_sqlMAFService = null;
_dataFeedService.Dispose();
_dataFeedService = null;
_dataService.CloseConnection();
_dataService = null;
}
#endregion implement IDisposable
}
The using block will dispose uss before it is done executing, so that's where your null reference exceptions are coming from (for both issues).
If UserStartupService is a singleton, and it could be used multiple times, then don't dispose it.
Also, I would recommend using await rather than callbacks (it's usually simpler), so something like this should work:
private async void LogOn_Click(object sender, RoutedEventArgs e)
{
btnLogon.IsEnabled = false;
// Create database service for DI
DataService _dataService = new DataService("MyData.sqlite");
var uss = UserStartupService.GetInstance(_dataService);
// progress bar...
CurrentProgress.Visibility = Windows.UI.Xaml.Visibility.Visible;
// create op and call...
var op = uss.SetUpUser(txtUserId.Text)
.AsTask(progress => { CurrentProgress.Value = progress; });
var result = await op;
txtMessage.Text = "Current user data already loaded...";
CurrentProgress.Value = 100;
btnLogon.IsEnabled = true;
}
Related
I want to use IAsyncEnumerable like a Source for akka streams. But I not found, how do it.
No sutiable method in Source class for this code.
using System.Collections.Generic;
using System.Threading.Tasks;
using Akka.Streams.Dsl;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
Source.From(await AsyncEnumerable())
.Via(/*some action*/)
//.....
}
private static async IAsyncEnumerable<int> AsyncEnumerable()
{
//some async enumerable
}
}
}
How use IAsyncEnumerbale for Source?
This has been done in the past as a part of Akka.NET Streams contrib package, but since I don't see it there anymore, let's go through on how to implement such source. The topic can be quite long, as:
Akka.NET Streams is really about graph processing - we're talking about many-inputs/many-outputs configurations (in Akka.NET they're called inlets and outlets) with support for cycles in graphs.
Akka.NET is not build on top of .NET async/await or even on top of .NET standard thread pool library - they're both pluggable, which means that the lowest barier is basically using callbacks and encoding what C# compiler sometimes does for us.
Akka.NET streams is capable of both pushing and pulling values between stages/operators. IAsyncEnumerable<T> can only pull data while IObservable<T> can only push it, so we get more expressive power here, but this comes at a cost.
The basics of low level API used to implement custom stages can be found in the docs.
The starter boilerplate looks like this:
public static class AsyncEnumerableExtensions {
// Helper method to change IAsyncEnumerable into Akka.NET Source.
public static Source<T, NotUsed> AsSource<T>(this IAsyncEnumerable<T> source) =>
Source.FromGraph(new AsyncEnumerableSource<T>(source));
}
// Source stage is description of a part of the graph that doesn't consume
// any data, only produce it using a single output channel.
public sealed class AsyncEnumerableSource<T> : GraphStage<SourceShape<T>>
{
private readonly IAsyncEnumerable<T> _enumerable;
public AsyncEnumerableSource(IAsyncEnumerable<T> enumerable)
{
_enumerable = enumerable;
Outlet = new Outlet<T>("asyncenumerable.out");
Shape = new SourceShape<T>(Outlet);
}
public Outlet<T> Outlet { get; }
public override SourceShape<T> Shape { get; }
/// Logic if to a graph stage, what enumerator is to enumerable.
protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) =>
new Logic(this);
sealed class Logic: OutGraphStageLogic
{
public override void OnPull()
{
// method called whenever a consumer asks for new data
}
public override void OnDownstreamFinish()
{
// method called whenever a consumer stage finishes,used for disposals
}
}
}
As mentioned, we don't use async/await straight away here: even more, calling Logic methods in asynchronous context is unsafe. To make it safe we need to register out methods that may be called from other threads using GetAsyncCallback<T> and call them via returned wrappers. This will ensure, that not data races will happen when executing asynchronous code.
sealed class Logic : OutGraphStageLogic
{
private readonly Outlet<T> _outlet;
// enumerator we'll call for MoveNextAsync, and eventually dispose
private readonly IAsyncEnumerator<T> _enumerator;
// callback called whenever _enumerator.MoveNextAsync completes asynchronously
private readonly Action<Task<bool>> _onMoveNext;
// callback called whenever _enumerator.DisposeAsync completes asynchronously
private readonly Action<Task> _onDisposed;
// cache used for errors thrown by _enumerator.MoveNextAsync, that
// should be rethrown after _enumerator.DisposeAsync
private Exception? _failReason = null;
public Logic(AsyncEnumerableSource<T> source) : base(source.Shape)
{
_outlet = source.Outlet;
_enumerator = source._enumerable.GetAsyncEnumerator();
_onMoveNext = GetAsyncCallback<Task<bool>>(OnMoveNext);
_onDisposed = GetAsyncCallback<Task>(OnDisposed);
}
// ... other methods
}
The last part to do are methods overriden on `Logic:
OnPull used whenever the downstream stage calls for new data. Here we need to call for next element of async enumerator sequence.
OnDownstreamFinish called whenever the downstream stage has finished and will not ask for any new data. It's the place for us to dispose our enumerator.
Thing is these methods are not async/await, while their enumerator's equivalent are. What we basically need to do there is to:
Call corresponding async methods of underlying enumerator (OnPull → MoveNextAsync and OnDownstreamFinish → DisposeAsync).
See, if we can take their results immediately - it's important part that usually is done for us as part of C# compiler in async/await calls.
If not, and we need to wait for the results - call ContinueWith to register our callback wrappers to be called once async methods are done.
sealed class Logic : OutGraphStageLogic
{
// ... constructor and fields
public override void OnPull()
{
var hasNext = _enumerator.MoveNextAsync();
if (hasNext.IsCompletedSuccessfully)
{
// first try short-path: values is returned immediately
if (hasNext.Result)
// check if there was next value and push it downstream
Push(_outlet, _enumerator.Current);
else
// if there was none, we reached end of async enumerable
// and we can dispose it
DisposeAndComplete();
}
else
// we need to wait for the result
hasNext.AsTask().ContinueWith(_onMoveNext);
}
// This method is called when another stage downstream has been completed
public override void OnDownstreamFinish() =>
// dispose enumerator on downstream finish
DisposeAndComplete();
private void DisposeAndComplete()
{
var disposed = _enumerator.DisposeAsync();
if (disposed.IsCompletedSuccessfully)
{
// enumerator disposal completed immediately
if (_failReason is not null)
// if we close this stream in result of error in MoveNextAsync,
// fail the stage
FailStage(_failReason);
else
// we can close the stage with no issues
CompleteStage();
}
else
// we need to await for enumerator to be disposed
disposed.AsTask().ContinueWith(_onDisposed);
}
private void OnMoveNext(Task<bool> task)
{
// since this is callback, it will always be completed, we just need
// to check for exceptions
if (task.IsCompletedSuccessfully)
{
if (task.Result)
// if task returns true, it means we read a value
Push(_outlet, _enumerator.Current);
else
// otherwise there are no more values to read and we can close the source
DisposeAndComplete();
}
else
{
// task either failed or has been cancelled
_failReason = task.Exception as Exception ?? new TaskCanceledException(task);
FailStage(_failReason);
}
}
private void OnDisposed(Task task)
{
if (task.IsCompletedSuccessfully) CompleteStage();
else {
var reason = task.Exception as Exception
?? _failReason
?? new TaskCanceledException(task);
FailStage(reason);
}
}
}
As of Akka.NET v1.4.30 this is now natively supported inside Akka.Streams via the RunAsAsyncEnumerable method:
var input = Enumerable.Range(1, 6).ToList();
var cts = new CancellationTokenSource();
var token = cts.Token;
var asyncEnumerable = Source.From(input).RunAsAsyncEnumerable(Materializer);
var output = input.ToArray();
bool caught = false;
try
{
await foreach (var a in asyncEnumerable.WithCancellation(token))
{
cts.Cancel();
}
}
catch (OperationCanceledException e)
{
caught = true;
}
caught.ShouldBeTrue();
I copied that sample from the Akka.NET test suite, in case you're wondering.
You can also use an existing primitive for streaming large collections of data. Here is an example of using Source.unfoldAsync to stream pages of data - in this case github repositories using Octokit - until there is no more.
var source = Source.UnfoldAsync<int, RepositoryPage>(startPage, page =>
{
var pageTask = client.GetRepositoriesAsync(page, pageSize);
var next = pageTask.ContinueWith(task =>
{
var page = task.Result;
if (page.PageNumber * pageSize > page.Total) return Option<(int, RepositoryPage)>.None;
else return new Option<(int, RepositoryPage)>((page.PageNumber + 1, page));
});
return next;
});
To run
using var sys = ActorSystem.Create("system");
using var mat = sys.Materializer();
int startPage = 1;
int pageSize = 50;
var client = new GitHubClient(new ProductHeaderValue("github-search-app"));
var source = ...
var sink = Sink.ForEach<RepositoryPage>(Console.WriteLine);
var result = source.RunWith(sink, mat);
await result.ContinueWith(_ => sys.Terminate());
class Page<T>
{
public Page(IReadOnlyList<T> contents, int page, long total)
{
Contents = contents;
PageNumber = page;
Total = total;
}
public IReadOnlyList<T> Contents { get; set; } = new List<T>();
public int PageNumber { get; set; }
public long Total { get; set; }
}
class RepositoryPage : Page<Repository>
{
public RepositoryPage(IReadOnlyList<Repository> contents, int page, long total)
: base(contents, page, total)
{
}
public override string ToString() =>
$"Page {PageNumber}\n{string.Join("", Contents.Select(x => x.Name + "\n"))}";
}
static class GitHubClientExtensions
{
public static async Task<RepositoryPage> GetRepositoriesAsync(this GitHubClient client, int page, int size)
{
// specify a search term here
var request = new SearchRepositoriesRequest("bootstrap")
{
Page = page,
PerPage = size
};
var result = await client.Search.SearchRepo(request);
return new RepositoryPage(result.Items, page, result.TotalCount);
}
}
I have an endpoint which runs a method. I want to ensure that method will not be executed while it's running when I hit the endpoint multiple times.
I imagine I can set a variable somewhere in the thread pool or something? I'm not sure how to go about investigating this.Some leads would be appreciated.
My example:
namespace Website.Import
{
public class ImportProducts : IHttpHandler
{
private static bool running = false;
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
if (running)
{
throw new Exception("Already running");
}
running = true;
try
{
var repo = new MemoryRepository();
var productImporter = new ProductImporter(repo);
var groupImporter = new GroupImporter(repo);
var discountImporter = new DiscountImporter(repo);
}
finally
{
running = false;
}
context.Response.Write("Done");
}
public bool IsReusable
{
get
{
return true;
}
}
}
}
You can create a lock object to ensure the action doesn't run in parallel.
private static object lockObject = new object();
lock (lockObject)
{
// your code
}
There might be a problem though: this method will get locked for every user since static variables are shared across all sessions.
This behavior might be intentional. If you want to block execution for all sessions, this code is fine. If you want to block execution for only this user, allowing the method to run once at the same time per user, you have to put the object in the session storage.
If you just want to inform the client it is already running, you could also throw an exception:
private static bool alreadyExecuting = false;
if (alreadyExecuting)
{
throw new Exception("Already running");
}
alreadyExecuting = true;
try
{
// your code
}
finally
{
alreadyExecuting = false;
}
Since I have converted my WCF methods to Async, my unit tests have failed, and I can't figure out the correct syntax to get them to work.
Cllient proxy class
public interface IClientProxy
{
Task DoSomething(CredentialDataList credentialData, string store);
}
service class
public class CredentialSync : ICredentialSync
{
private ICredentialRepository _repository;
private IClientProxy _client;
public CredentialSync()
{
this._repository = new CredentialRepository();
this._client = new ClientProxy();
}
public CredentialSync(ICredentialRepository repository, IClientProxy client)
{
this._repository = repository;
this._client = client;
}
public async Task Synchronise(string payrollNumber)
{
try
{
if (string.IsNullOrEmpty(payrollNumber))
{
.... some code
}
else
{
CredentialDataList credentialData = new CredentialDataList();
List<CredentialData> credentialList = new List<CredentialData>();
// fetch the record from the database
List<GetCredentialData_Result> data = this._repository.GetCredentialData(payrollNumber);
var pinData = this._repository.GetCredentialPinData(payrollNumber);
// get the stores for this employee
var storeList = data.Where(a => a.StoreNumber != null)
.GroupBy(a => a.StoreNumber)
.Select(x => new Store { StoreNumber = x.Key.ToString() }).ToArray();
var credential = this.ExtractCredentialData(data, pinData, payrollNumber);
credentialList.Add(credential);
credentialData.CredentialList = credentialList;
foreach (var store in storeList)
{
//this line causes an Object reference not set to an instance of an object error
await _client.DoSomething(credentialData, store.StoreNumber);
}
}
}
catch (Exception ex)
{
throw new FaultException<Exception>(ex);
}
}
Test Class
/// </summary>
[TestClass]
public class SynchTest
{
private Mock<ICredentialRepository> _mockRepository;
private Mock<IClientProxy> _mockService;
[TestInitialize]
public void Setup()
{
... some setups for repository which work fine
}
[TestMethod]
public async Task SynchroniseData_WithOneEmployee_CallsReplicateService()
{
this._mockService = new Mock<IClientProxy>();
this._mockService.Setup(x=>x.DoSomething(It.IsAny<CredentialDataList>(), It.IsAny<string>()));
// arrange
string payrollNumber = "1";
CredentialSync service = new CredentialSync(this._mockRepository.Object, this._mockService.Object);
// act
await service.Synchronise(payrollNumber);
// assert
this._mockService.VerifyAll();
}
The error is when ClientProxy.DoSomething is called:
Object reference not set to an instance of an object
The parameters are both fine.
If I convert my ClientProxy.DoSomething method to a synchronous method
(public void DoSomething(...) )the code works fine, but I do need this to be called asynchronously
DoSomething returns null instead of returning a Task, and so you get an exception when awaiting it. You need to specify when building the mock that it should return a Task.
In this case it seems that you can simply return an already completed task using Task.FromResult so the mock setup should look like this:
this._mockService.Setup(...).Returns(Task.FromResult(false));
Beginning with the next version of .Net (4.6) you can use Task.CompletedTask like this:
this._mockService.Setup(...).Returns(Task.CompletedTask);
You can reduce the amount of clutter in the code by using ReturnsAsync
this._mockService.Setup(...).ReturnsAsync(false);
This way you can remove the Task.FromResult part of the code
I think you need to return the Task from the DoSomething mock
this._mockService.Setup(x => x.DoSomething(It.IsAny<CredentialDataList>(), It.IsAny<string>()))
.Returns(Task.FromResult<int>(0));
I have a reoccurring pattern in my WPF MVVM applications that has the following structure.
public class MyViewModel : NotificationObject
{
private readonly IService _DoSomethingService;
private bool _IsBusy;
public bool IsBusy
{
get { return _IsBusy; }
set
{
if (_IsBusy != value)
(
_IsBusy = value;
RaisePropertyChanged(() => IsBusy);
)
}
}
public ICommand DisplayInputDialogCommand { get; private set; }
public InteractionRequest<Notification> Error_InteractionRequest { get; private set; }
public InteractionRequest<Confirmation> GetInput_InteractionRequest { get; private set; }
// ctor
public MyViewModel(IService service)
{
_DoSomethingService = service;
DisplayInputDialogCommand = new DelegateCommand(DisplayInputDialog);
Error_InteractionRequest = new InteractionRequest<Notification>();
Input_InteractionRequest = new InteractionRequest<Confirmation>();
}
private void DisplayInputDialog()
{
Input_InteractionRequest.Raise(
new Confirmation() {
Title = "Please provide input...",
Content = new InputViewModel()
},
ProcessInput
);
}
private void ProcessInput(Confirmation context)
{
if (context.Confirmed)
{
IsBusy = true;
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(DoSomethingWorker_DoWork);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(DoSomethingWorker_RunWorkerCompleted);
bg.RunWorkerAsync();
}
}
private void DoSomethingWorker_DoWork(object sender, DoWorkEventArgs e)
{
_DoSomethingService.DoSomething();
}
private void DoSomethingWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
IsBusy = false;
if (e.Error != null)
{
Error_InteractionRequest.Raise(
new Confirmation() {
Title = "Error",
Content = e.Error.Message
}
);
}
}
}
Essentially, the pattern describes a dialog oriented workflow that allows the user to initiate (and provide input to) a long running operation without locking the UI. A concrete example of this pattern might be a "Save As..." operation where the user clicks a "Save As..." button, then keys in a text value for filename in a popup dialog, then clicks the dialog OK button, then watches a spin animation while their data is saved under the specified filename.
In the provided code example, initiating this workflow will perform the following operations.
Raise the Input_InteractionRequest Raised event to display a dialog in the UI for the purpose of collecting user input.
Invoke the ProcessInput callback (triggered when the user completes the dialog).
Check the Confirmed property of the InteractionRequest context to determine if the dialog was confirmed or canceled.
If confirmed...
Set the IsBusy flag.
Start a BackgroundWorker to perform the long running _DoSomethingService.DoSomething() operation.
Unset the IsBusy flag.
If an error occurred in DoSomething_DoWork, raise the Error_InteractionRequest Raised event to display a message box in the UI for the purpose of informing the user that the operation was not successful.
I would like to maximize unit testing coverage for this pattern, but I'm not quite sure how to approach it. I would like to avoid unit testing non-public members directly since the specific implementation of this pattern could change over time and in fact varies from instance to instance throughout my applications. I have considered the following options, but none of them seem appropriate.
Replace BackgroundWorker with IBackgroundWorker and inject it via ctor. Use a synchronous IBackgroundWorker during tests to ensure that unit tests do not complete before DoWork/RunWorkerCompleted methods are called. This would require a lot of refactoring and does not address testing the InteractionRequest callback either.
Use System.Threading.Thread.Sleep(int) to allow the BackgroundWorker operation to complete before the assertion stage. I don't like this because it is slow and I still don't know how to test code paths in the InteractionRequest callback.
Refactor the BackgroundWorker methods and InteractionRequest callback into Humble Objects that can be syncronously and independently tested. This seems promising, but structuring it has me stumped.
Unit test DoSomethingWorker_DoWork, DoSomethingWorker_RunWorkerCompleted, and ProcessInput synchronously and independently. This would give me the coverage I need, but I would be testing against a specific implementation rather than the public interface.
What is the best way to unit test and/or refactor the above pattern to provide maximum code coverage?
EDIT: See update below for simpler alternative (.NET 4.0+ only).
This pattern can be easily tested by abstracting the mechanics of BackgroundWorker behind an interface and then testing against that interface as described in this question. Once the quirks of the BackgroundWorker have been obscured behind an interface, testing the InteractionRequest becomes straightforward.
This is the interface I decided to use.
public interface IDelegateWorker
{
void Start<TInput, TResult>(Func<TInput, TResult> onStart, Action<TResult> onComplete, TInput parm);
}
This interface exposes a single Start method that accepts the following parameters.
Func<TInput, TResult> onStart - Comparable to BackgroundWorker.DoWork. This is where you would perform the primary work of your background operation. This delegate should accept a single parameter of type TInput and return a value of type TResult which should be passed on to the onComplete delegate.
Action<TResult> onComplete - Comparable to BackgroundWorker.RunWorkerCompleted. This delegate will be invoked after the onStart delegate completes. This is where you would perform any post-processing work. This delegate should accept a single parameter of type TResult.
TInput parm - The initial value to pass into the onStart delegate (or null if the onStart delegate does not require input). Comparable to passing an argument value to the Backgroundworker.RunWorkerAsync(object argument) method.
You can then use dependency injection to replace the BackgroundWorker instance with an instance of IDelegateWorker. For example, the rewritten MyViewModel now looks like this.
public class MyViewModel : NotificationObject
{
// Dependencies
private readonly IService _doSomethingService;
private readonly IDelegateWorker _delegateWorker; // new
private bool _IsBusy;
public bool IsBusy
{
get { return _IsBusy; }
set
{
if (_IsBusy != value)
{
_IsBusy = value;
RaisePropertyChanged(() => IsBusy);
}
}
}
public ICommand DisplayInputDialogCommand { get; private set; }
public InteractionRequest<Notification> ErrorDialogInteractionRequest { get; private set; }
public InteractionRequest<Confirmation> InputDialogInteractionRequest { get; private set; }
// ctor
public MyViewModel(IService service, IDelegateWorker delegateWorker /* new */)
{
_doSomethingService = service;
_delegateWorker = delegateWorker; // new
DisplayInputDialogCommand = new DelegateCommand(DisplayInputDialog);
ErrorDialogInteractionRequest = new InteractionRequest<Notification>();
InputDialogInteractionRequest = new InteractionRequest<Confirmation>();
}
private void DisplayInputDialog()
{
InputDialogInteractionRequest.Raise(
new Confirmation()
{
Title = "Please provide input...",
Content = new DialogContentViewModel()
},
ProcessInput
);
}
private void ProcessInput(Confirmation context)
{
if (context.Confirmed)
{
IsBusy = true;
// New - BackgroundWorker now abstracted behind IDelegateWorker interface.
_delegateWorker.Start<object, TaskResult<object>>(
ProcessInput_onStart,
ProcessInput_onComplete,
null
);
}
}
private TaskResult<object> ProcessInput_onStart(object parm)
{
TaskResult<object> result = new TaskResult<object>();
try
{
result.Result = _doSomethingService.DoSomething();
}
catch (Exception ex)
{
result.Error = ex;
}
return result;
}
private void ProcessInput_onComplete(TaskResult<object> tr)
{
IsBusy = false;
if (tr.Error != null)
{
ErrorDialogInteractionRequest.Raise(
new Confirmation()
{
Title = "Error",
Content = tr.Error.Message
}
);
}
}
// Helper Class
public class TaskResult<T>
{
public Exception Error;
public T Result;
}
}
This technique allows you to avoid the quirks of the BackgroundWorker class by injecting a syncronous (or mock) implementation of IDelegateWorker into MyViewModel when testing and an asyncronous implementation for production. For example, you could use this implementation when testing.
public class DelegateWorker : IDelegateWorker
{
public void Start<TInput, TResult>(Func<TInput, TResult> onStart, Action<TResult> onComplete, TInput parm)
{
TResult result = default(TResult);
if (onStart != null)
result = onStart(parm);
if (onComplete != null)
onComplete(result);
}
}
And you could use this implementation for production.
public class ASyncDelegateWorker : IDelegateWorker
{
public void Start<TInput, TResult>(Func<TInput, TResult> onStart, Action<TResult> onComplete, TInput parm)
{
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += (s, e) =>
{
if (onStart != null)
e.Result = onStart((TInput)e.Argument);
};
bg.RunWorkerCompleted += (s, e) =>
{
if (onComplete != null)
onComplete((TResult)e.Result);
};
bg.RunWorkerAsync(parm);
}
}
With this infrastructure in place, you should be able to test all aspects of your InteractionRequest as follows. Note that I am using MSTest and Moq and have achieved 100% coverage according to the Visual Studio Code Coverage tool although that number is somewhat suspect to me.
[TestClass()]
public class MyViewModelTest
{
[TestMethod()]
public void DisplayInputDialogCommand_OnExecute_ShowsDialog()
{
// Arrange
Mock<IService> mockService = new Mock<IService>();
Mock<IDelegateWorker> mockWorker = new Mock<IDelegateWorker>();
MyViewModel vm = new MyViewModel(mockService.Object, mockWorker.Object);
InteractionRequestTestHelper<Confirmation> irHelper
= new InteractionRequestTestHelper<Confirmation>(vm.InputDialogInteractionRequest);
// Act
vm.DisplayInputDialogCommand.Execute(null);
// Assert
Assert.IsTrue(irHelper.RequestRaised);
}
[TestMethod()]
public void DisplayInputDialogCommand_OnExecute_DialogHasCorrectTitle()
{
// Arrange
const string INPUT_DIALOG_TITLE = "Please provide input...";
Mock<IService> mockService = new Mock<IService>();
Mock<IDelegateWorker> mockWorker = new Mock<IDelegateWorker>();
MyViewModel vm = new MyViewModel(mockService.Object, mockWorker.Object);
InteractionRequestTestHelper<Confirmation> irHelper
= new InteractionRequestTestHelper<Confirmation>(vm.InputDialogInteractionRequest);
// Act
vm.DisplayInputDialogCommand.Execute(null);
// Assert
Assert.AreEqual(irHelper.Title, INPUT_DIALOG_TITLE);
}
[TestMethod()]
public void DisplayInputDialogCommand_OnExecute_SetsIsBusyWhenDialogConfirmed()
{
// Arrange
Mock<IService> mockService = new Mock<IService>();
Mock<IDelegateWorker> mockWorker = new Mock<IDelegateWorker>();
MyViewModel vm = new MyViewModel(mockService.Object, mockWorker.Object);
vm.InputDialogInteractionRequest.Raised += (s, e) =>
{
Confirmation context = e.Context as Confirmation;
context.Confirmed = true;
e.Callback();
};
// Act
vm.DisplayInputDialogCommand.Execute(null);
// Assert
Assert.IsTrue(vm.IsBusy);
}
[TestMethod()]
public void DisplayInputDialogCommand_OnExecute_CallsDoSomethingWhenDialogConfirmed()
{
// Arrange
Mock<IService> mockService = new Mock<IService>();
IDelegateWorker worker = new DelegateWorker();
MyViewModel vm = new MyViewModel(mockService.Object, worker);
vm.InputDialogInteractionRequest.Raised += (s, e) =>
{
Confirmation context = e.Context as Confirmation;
context.Confirmed = true;
e.Callback();
};
// Act
vm.DisplayInputDialogCommand.Execute(null);
// Assert
mockService.Verify(s => s.DoSomething(), Times.Once());
}
[TestMethod()]
public void DisplayInputDialogCommand_OnExecute_ClearsIsBusyWhenDone()
{
// Arrange
Mock<IService> mockService = new Mock<IService>();
IDelegateWorker worker = new DelegateWorker();
MyViewModel vm = new MyViewModel(mockService.Object, worker);
vm.InputDialogInteractionRequest.Raised += (s, e) =>
{
Confirmation context = e.Context as Confirmation;
context.Confirmed = true;
e.Callback();
};
// Act
vm.DisplayInputDialogCommand.Execute(null);
// Assert
Assert.IsFalse(vm.IsBusy);
}
[TestMethod()]
public void DisplayInputDialogCommand_OnExecuteThrowsError_ShowsErrorDialog()
{
// Arrange
Mock<IService> mockService = new Mock<IService>();
mockService.Setup(s => s.DoSomething()).Throws(new Exception());
DelegateWorker worker = new DelegateWorker();
MyViewModel vm = new MyViewModel(mockService.Object, worker);
vm.InputDialogInteractionRequest.Raised += (s, e) =>
{
Confirmation context = e.Context as Confirmation;
context.Confirmed = true;
e.Callback();
};
InteractionRequestTestHelper<Notification> irHelper
= new InteractionRequestTestHelper<Notification>(vm.ErrorDialogInteractionRequest);
// Act
vm.DisplayInputDialogCommand.Execute(null);
// Assert
Assert.IsTrue(irHelper.RequestRaised);
}
[TestMethod()]
public void DisplayInputDialogCommand_OnExecuteThrowsError_ShowsErrorDialogWithCorrectTitle()
{
// Arrange
const string ERROR_TITLE = "Error";
Mock<IService> mockService = new Mock<IService>();
mockService.Setup(s => s.DoSomething()).Throws(new Exception());
DelegateWorker worker = new DelegateWorker();
MyViewModel vm = new MyViewModel(mockService.Object, worker);
vm.InputDialogInteractionRequest.Raised += (s, e) =>
{
Confirmation context = e.Context as Confirmation;
context.Confirmed = true;
e.Callback();
};
InteractionRequestTestHelper<Notification> irHelper
= new InteractionRequestTestHelper<Notification>(vm.ErrorDialogInteractionRequest);
// Act
vm.DisplayInputDialogCommand.Execute(null);
// Assert
Assert.AreEqual(irHelper.Title, ERROR_TITLE);
}
[TestMethod()]
public void DisplayInputDialogCommand_OnExecuteThrowsError_ShowsErrorDialogWithCorrectErrorMessage()
{
// Arrange
const string ERROR_MESSAGE_TEXT = "do something failed";
Mock<IService> mockService = new Mock<IService>();
mockService.Setup(s => s.DoSomething()).Throws(new Exception(ERROR_MESSAGE_TEXT));
DelegateWorker worker = new DelegateWorker();
MyViewModel vm = new MyViewModel(mockService.Object, worker);
vm.InputDialogInteractionRequest.Raised += (s, e) =>
{
Confirmation context = e.Context as Confirmation;
context.Confirmed = true;
e.Callback();
};
InteractionRequestTestHelper<Notification> irHelper
= new InteractionRequestTestHelper<Notification>(vm.ErrorDialogInteractionRequest);
// Act
vm.DisplayInputDialogCommand.Execute(null);
// Assert
Assert.AreEqual((string)irHelper.Content, ERROR_MESSAGE_TEXT);
}
// Helper Class
public class InteractionRequestTestHelper<T> where T : Notification
{
public bool RequestRaised { get; private set; }
public string Title { get; private set; }
public object Content { get; private set; }
public InteractionRequestTestHelper(InteractionRequest<T> request)
{
request.Raised += new EventHandler<InteractionRequestedEventArgs>(
(s, e) =>
{
RequestRaised = true;
Title = e.Context.Title;
Content = e.Context.Content;
});
}
}
}
Notes:
Another option is to use the commercial version of the TypeMock isolation (mocking) framework. This framework is ideal for legacy code or code that is otherwise not well suited for unit testing. TypeMock allows you to mock just about anything. I will not go into the specifics of how this could be used for the question at hand, but it is still worth pointing out that it is a valid option.
In .NET 4.5 use of BackgroundWorker is deprecated in favor of the async/await pattern. The use of the IDelegateWorker (or some similar) interface as described above allows your entire project to migrate to the async/await pattern without the need to modify a single ViewModel.
Update:
After implementing the technique described above, I discovered a simpler approach for .NET 4.0 or better. To unit test an asynchronous process, you need some way to detect when that process is complete or you need to be able to run that process synchronously during tests.
Microsoft introduced the Task Parallel Library (TPL) in .NET 4.0. This library provides a rich set of tools for performing asynchronous operations that go far beyond the capabilities of the BackgroundWorker class. The best way to implement an asynchronous operation is to use the TPL and then return a Task from your method under test. Unit testing an asynchronous operation implemented in this way is then trivial.
[TestMethod]
public void RunATest()
{
// Assert.
var sut = new MyClass();
// Act.
sut.DoSomethingAsync().Wait();
// Assert.
Assert.IsTrue(sut.SomethingHappened);
}
If it is impossible or impractical to expose the task to your unit test, then the next best option is to override the way that tasks are scheduled. By default tasks are scheduled to run asynchronously on the ThreadPool. You can override this behavior by specifying a custom scheduler in code. For example, the following code will run a task using the UI thread.
Task.Factory.StartNew(
() => DoSomething(),
TaskScheduler.FromCurrentSynchronizationContext());
To implement this in a way that is unit testable, pass the task scheduler in using Dependency Injection. Your unit tests can then pass in a task scheduler that performs the operation synchronously on the current thread and your production application will pass in a task scheduler that runs the tasks asynchronously on the ThreadPool.
You can even go a step further and eliminate the dependency injection by overriding the default task scheduler using reflection. This makes your unit tests a little more brittle, but is less invasive to the actual code you are testing. For a great explanation on why this works, see this blog post.
// Configure the default task scheduler to use the current synchronization context.
Type taskSchedulerType = typeof(TaskScheduler);
FieldInfo defaultTaskSchedulerField = taskSchedulerType.GetField("s_defaultTaskScheduler", BindingFlags.SetField | BindingFlags.Static | BindingFlags.NonPublic);
defaultTaskSchedulerField.SetValue(null, TaskScheduler.FromCurrentSynchronizationContext());
Unfortunately, this will not work as expected from a unit test assembly. This is because unit tests, like Console applications, do not have a SynchronizationContext and you will get the following error message.
Error: System.InvalidOperationException: The current SynchronizationContext may not be used as a TaskScheduler.
To fix this you just need to set the SynchronizationContext in your test setup.
// Configure the current synchronization context to process work synchronously.
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
This will get rid of the error, but some of your tests may still fail. This is because the default SynchronizationContext posts work asynchronously to the ThreadPool. To override this, simply subclass the default SynchronizationContext and override the Post method as follows.
public class TestSynchronizationContext : SynchronizationContext
{
public override void Post(SendOrPostCallback d, object state)
{
Send(d, state);
}
}
With this in place, your test setup should look like the code below and all of the Tasks in your code under test will run synchronously by default.
// Configure the current synchronization context to process work synchronously.
SynchronizationContext.SetSynchronizationContext(new TestSynchronizationContext());
// Configure the default task scheduler to use the current synchronization context.
Type taskSchedulerType = typeof(TaskScheduler);
FieldInfo defaultTaskSchedulerField = taskSchedulerType.GetField("s_defaultTaskScheduler", BindingFlags.SetField | BindingFlags.Static | BindingFlags.NonPublic);
defaultTaskSchedulerField.SetValue(null, TaskScheduler.FromCurrentSynchronizationContext());
Note that this does not prevent a Task from being started with a custom scheduler. In such a case, you would need to pass that custom scheduler in using Dependency Injection and then pass in a synchronous scheduler during tests.
Good Question. I will be trying your option 3 with some slight changes.
Make InteractionRequest testable, such that the test method can choose whether to confirm or cancel the operation. So this allows testing the individual paths. You can use IoC technique (inversion of control )
Refactor all logic in DoWork & RunWorkerCompleted to separate methods, this allows to test these methods independently (if required).
Then add a new flag IsAsyncFlag to indicate if this needs to be executed asynchronously or not. Turn off the Async mode when running the tests.
There is a lot of emphasize on the test coverage. But in my experience 100% test coverage is very difficult to achieve and it can never be a synonym to code quality. Hence my focus is in identifying & writing tests that would add value to the solution.
If you have found a better approach, please share.
I'm attempting to make a StateMachine execute some database action between states.
So I have a "starting" state that uses CallExternalMethodActivity to call a "BeginExecuteNonQuery" function on an class decorated with ExternalDataExchangeAttribute. After that it uses a SetStateActivity to change to an "ending" state.
The "ending" state uses a HandleExternalEventActivity to listen to a "EndExecuteNonQuery" event.
I can step through the local service, into the "BeginExecuteNonQuery" function.
The problem is that the "EndExecuteNonQuery" is null.
public class FailoverWorkflowController : IFailoverWorkflowController
{
private readonly WorkflowRuntime workflowRuntime;
private readonly FailoverWorkflowControlService failoverWorkflowControlService;
private readonly DatabaseControlService databaseControlService;
public FailoverWorkflowController()
{
workflowRuntime = new WorkflowRuntime();
workflowRuntime.WorkflowCompleted += workflowRuntime_WorkflowCompleted;
workflowRuntime.WorkflowTerminated += workflowRuntime_WorkflowTerminated;
ExternalDataExchangeService dataExchangeService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataExchangeService);
databaseControlService = new DatabaseControlService();
workflowRuntime.AddService(databaseControlService);
workflowRuntime.StartRuntime();
}
...
}
...
public void BeginExecuteNonQuery(string command)
{
Guid workflowInstanceID = WorkflowEnvironment.WorkflowInstanceId;
ThreadPool.QueueUserWorkItem(delegate(object state)
{
try
{
int result = ExecuteNonQuery((string)state);
EndExecuteNonQuery(null, new ExecuteNonQueryResultEventArgs(workflowInstanceID, result));
}
catch (Exception exception)
{
EndExecuteNonQuery(null, new ExecuteNonQueryResultEventArgs(workflowInstanceID, exception));
}
}, command);
}
What am I doing wrong with my implementation?
-Stan
I can't tell from the code snippet but make sure you are using the ExternalDataExchangeService to host your service and don't add you service directly to the runtime. The ExternalDataExchangeService is responsible for adding the required eventhandlers and turning the events into queued messages for the workflow.
I'm using ExternalDataExchangeService without code by changing my config file as shown here :