How to Unit Test BeginInvoke on an Action - c#

I am looking for a way to test BeginInvoke on an Action method, since the method runs on a background thread there is no way of knowing when it actually completes or calls callback method. I am looking for a way to keep my test wait until the callback gets called before making assertions.
In the following Presenter class, you can notice that I am invoking PopulateView on background thread which updates the view when data is fetched and I am trying assert the view Properties are correctly initialized.
I am using NUnit and Moq.
public class Presenter
{
private IView _view;
private IService _service;
public Presenter(IView view, IService service)
{
_view = view;
_service = service;
Action action = PopulateView;
action.BeginInvoke(PopulateViewCallback, action);
}
private void PopulateViewCallback(IAsyncResult ar)
{
try
{
Action target = (Action)ar.AsyncState;
target.EndInvoke(ar);
}
catch (Exception ex)
{
Logger.Instance.LogException("Failed to initialize view", ex);
}
}
private void PopulateView()
{
Thread.Sleep(2000); // Fetch data _service.DoSomeThing()
_view.Property1 = "xyz";
}
}

Abstract your code so that you can inject the behavior you want at testing time.
public class MethodInvoker
{
public virtual void InvokeMethod(Action method, Action callback)
{
method.BeginInvoke(callback, method);
}
}
This version is asynchronous. At testing time, you can simply make a blocking version:
public class TestInvoker
{
public IAsyncResult MockResult { get; set; }
public override void InvokeMethod(Action method, Action callback)
{
method();
callback(MockResult);
}
}
Then your code simply changes to this:
// Inject this dependency
Invoker.InvokeMethod(PopulateView, PopulateViewCallback);
At runtime, it's asynchronous. At testing time, it blocks the call.

BeginInvoke() returns an IAsyncResult which you can use to wait.
IAsynchResult ar = action.BeginInvoke(...);
ar.AsyncWaitHandle.WaitOne();

You don't need to check that methods are called instead test the end result - in this case that _view.Propert1 == "xyz".
Because it's an async call you might need to have a loop that Asserts periodically that the value has been set, also a timeout on the test or the check is a must otherwise your test would never fail (just stuck).
You might consider stubbing out the action (PopulateView) in order to skip the Sleep.

Related

Unit Testing ICommand and Methods

I have developed an WPF application using MVVM as a architecture and am writing some unit tests as part of this. In my view I have a button that is bound to a property in the ViewModel which can be seen below.
ViewModel
public ICommand MoreInfoCommand
{
get
{
if (_moreInfoCommand == null)
{
_moreInfoCommand = new RelayCommand(parameter => OpenLink());
}
return _moreInfoCommand;
}
}
private void OpenLink()
{
try
{
Process.Start("https://www.google.com/");
}
catch
{
// catch error...
}
}
In my unit testing I have created the following unit test:
UnitTest
[Description("Test MoreInfoCommand")]
[TestMethod]
public void TestMoreInfoCommand()
{
viewModel vm = new viewModel();
Assert.IsTrue(vm.MoreInfoCommand.CanExecute(null));
}
Currently this tests the the property to see if when the button is clicked in the UI the relevant method can be executed. This passes as the conditions are met, however its my understanding I need to test the functionality as well. With this in mind how do I, for example tests that the correct functionality occurs when the button is clicked. I.e how to test what occurs when the ICommand MoreInfoCommand is executed as a result of button click in the UI.
I know private methods can be tested directly, but should in my unit testing I be checking the functionality as well and if so, how can I do this.
Thanks in advance.
Your view model isn't really testable. If you want to it to be, you should replace the call to the static Process.Start method with a call to a method of a interface that you inject the view model with:
public ViewModel(IProcessLoader processLoader) =>
_processLoader = processLoader;
//...
private void OpenLink()
{
try
{
_processLoader.Start("https://www.google.com/");
}
catch
{
// catch error...
}
}
You could then mock the interface in your unit test, for example using a mocking framwork like Moq:
[TestMethod]
public void TestMoreInfoCommand()
{
//Arrange
Mock<IProcessLoader> processLoader = new Mock<IProcessLoader>();
viewModel vm = new viewModel(processLoader.Object);
ICommand command = vm.MoreInfoCommand;
//Act
command.Execute(null);
//Assert
processLoader.Verify(x => x.Start(It.IsAny<string>()));
}
In the real app, you would implement the interface as a wrapper around Process.Start:
public interface IProcessLoader
{
void Start(string s);
}
public class ProcessLoader : IProcessLoader
{
public void Start(string s) => Process.Start(s);
}
It's important to realize that you should only verify that the method is called from the view model. A unit test against the view model class should not test the functionality of the Process class. The resposibility of the view model ends when Start has been called.
.NET and the underlying OS is responsible for what the Process class actually does. You should not test this but only your own code.
vm.MoreInfoCommand.CanExecute(null) would only call the canExecute method in your RelayCommand, but you did not provide any. CanExecute tells nothing about whether OpenLink would perform successfully or not.
Although I am no unit test specialist, if your code real looks like this, I doubt if it's worth to write a unit test for it in the first place, because it is so very simple.
As the comment from user auburg states, you can check, whether the process starts, although the process's name would depend on which browser was the standard browser. Also, you would have to wait for some time for the process to start. And maybe there was a process with the same name already running, lots of chances for trouble.
If you really want, you can check, if one of the well known mocking frameworks, e.g. Moq or Rhino Mocks, is able to mock away Process.Start.

Async NUnit Test Method passing post the await call

I am writing NUnit Test for async methods and am using extent reporting to report the results. The ExtentTest linked to my test get completed as soon as the await step i the test method has completed execution and am no longer able to access the ExtentTest for any logging purpose. Is there any issue with my code or is this expected ?
Here is my Test method:
[Test, RequiresThread]
public async Task GetList()
{
try
{
ReportHelper.ExtentTestInfo("system.readResources() method is called");
Resources resources = await system.readResources();
ReportHelper.ExtentTestInfo("system.readResources() method finished and responded");
//Test Assertions
}
}
Here is my ReportHelper class:
public class ReportHelper
{
private static ExtentReports TestReportHTML = new ExtentReports();
var htmlReporter = new ExtentV3HtmlReporter("Test_Run_Report_" + #".html");
TestReportHTML.AttachReporter(htmlReporter);
[ThreadStatic] private static ExtentTest _extentTest;
_extentTest = TestReportHTML.CreateTest(testName); //testName is passed during [SetUp]
public static void ExtentTestInfo(string testInfo)
{
_extentTest.Info(testInfo);
}
}
Once the await call has been executed the _extentTest status is passed and on the next line I am getting NullReferenceException for the _extentTest
You need to remove the [ThreadStatic] attribute. That stops the variable being shared between threads but await may cause the code to execute the remaining code on a different thread, which is causing your _extentTest to be null after the await.

Exception not thrown by mocked object

Objective is to unit test a PUBLIC VOID Method.
I have a mocked service, which my class-under-test would call, in a for-each loop with 3 different parameters.
The class-under-test passes some input parameters to "SendRequest" method of the service which executes using those parameters.
I want the mocked service to throw an exception when one of the parameters has a specific value e.g "abc".
I use something like this:
public class ClassUnderTest
{
private IMyService _myservice;
public ClassUnderTest(IMyService myservice)
{
_myservice = myservice;
}
public void MyMethod()
{
//assume I get those 3 values from somewhere, in here.
var list = new List<string>{"abc","aaa","bbb"};
foreach(var item in list)
{
try
{
_myservice.SendRequest(item);
}
catch(Exception ex)
{
//do some logging and continue calling service with next item in list
}
}
}
}
var myService = new Mock<IMyService>();
myService.Setup(x => x.SendRequest("abc")).Throws<Exception>();
myService.Setup(x => x.SendRequest("aaa"));
myService.Setup(x => x.SendRequest("bbb"));
var classUnderTest = new ClassUnderTest(myService.Object);
classUnderTest.MyMethod();
myService.Verify(x =>x.SendRequest(It.IsAny<string>()), Times.Exactly(2));
More Context:
As MyMethod returns void, to test it, I can only rely on the the fact that my dependencies were invoked at different portions of the code in this method. For e.g. if there is a null check for input parameters before service call, the method would return before it invokes the service. If it goes past null check, the dependency service would be invoked. I would be able to trace these in the code coverage results( and in debug mode).
When I run the test, it fails because its invoking the service thrice but I expect the invocation to happen twice(now may be I am wrong and may be that although it is supposed to throw exception the invocation attempt is still counted by Verify call and hence I get 3 runs).
Whatever be the case, on debug I see that the service never throws exception. I have a try-catch in the for-each-loop where I want to do some logging and continue calling the service again with the next value. But I never get to get inside the Catch block.
What am I doing wrong?
Option 1: Specific Exception
My 1st suggestion would throw a more specific exception so you can be more sure.
Option 2: Inject an ILogger service
Refactor out the logging into an ILogger and inject that in. Then pass a mock of that in and assert against it.
Option 3: Extract and Override
If you must check catch block was hit you can use extract and override:
public class ClassUnderTest
{
private IMyService _myservice;
public ClassUnderTest(IMyService myservice)
{
_myservice = myservice;
}
public void MyMethod()
{
//assume I get those 3 values from somewhere, in here.
var list = new List<string>{"abc","aaa","bbb"};
foreach(var item in list)
{
try
{
_myservice.SendRequest(item);
}
catch(Exception ex)
{
LogError(ex);
}
}
}
protected virtual LogException(Exception ex)
{
//do logging
}
}
public class TestableClassUnderTest : ClassUnderTest
{
public bool LoggingWasCalled { get; set; }
protected virtual LogException(Exception ex)
{
LoggingWasCalled = true;
}
}
Then you could sheck something like this:
var testableSut = new TestableClassUnderTest ();
testableSut.MyMethod("abc");
Assert.True(testableSut.LoggingWasCalled);
I walk through it in more detail here: http://devonburriss.me/testing-the-untestable/

How to return data using await function in C# windows phone 8?

I'm new to C#. I
I've a problem related to async methods and await function in C# windows phone 8.0.
I've this http request and can get response. This is working fine and There is no issue...
public async static Task<List<MyAccountData>> GetBalance()
{
HttpClient = new HttpClient();
string response = await client.GetStringAsync("http://xxxx/xxx/xxx");
List<MyAccountData> data = JsonConvert.DeserializeObject<List<MyAccountData>>(response);
return data;
}
I've another class call MainModel
public class MainModel
{
public void LoadData()
{
}
}
So My problem is, I want to call that GetBalance method with in MainModel class and parse data to LoadData method(simply want 2 access Data with in LoadData method). LoadData method can't change return type or can't use async. So how is this possible?
If you want a responsive UI - i.e., one that has a chance of being accepted in the store - then blocking on the async operation is not an option.
Instead, you have to think a bit about how you want your UI to look while the operation is in progress. And while you're thinking about that, also think about how you would want your UI to respond if the operation errors out.
Then you can code up a solution. It's possible to do this with async void, if you catch all exceptions and handle them cleanly:
public async void LoadData()
{
try
{
... // Set up "loading" UI state.
var balance = await GetBalanceAsync();
... // Set up "normal" UI state.
Balance = balance;
}
catch
{
... // Set up "error" UI state.
}
}
However, I prefer to use a type I created called NotifyTaskCompletion, which is a data-bindable wrapper for Task<T> (described in my MSDN article). Using NotifyTaskCompletion, the LoadData becomes much simpler:
public void LoadData()
{
GetBalanceOperation = new NotifyTaskCompletion<Balance>(GetBalanceAsync());
}
public NotifyTaskCompletion<Balance> GetBalanceOperation // Raises INotifyPropertyChanged when set
Then your UI can data-bind to properties on NotifyTaskCompletion<T>, such as IsNotCompleted (for the "loading" state), IsSuccessfullyCompleted and Result (for the "normal" state), and IsFaulted and ErrorMessage (for the "error" state).
There is no difference to use async await in Windows Phone 8 dev:
public class MainModel
{
public async void LoadData()
{
var data = await Foo.GetBalance();
}
}
Depends on whether you want LoadData to be synchronous (not returning until all the data has been streamed in over HTTP, and locking up the UI until then), or to begin the process and return immediately. If you can't change LoadData to async, then those are your only two options.
If you want LoadData to be synchronous:
public void LoadData() {
var task = GetBalance();
var result = task.Result; // will lock up the UI until the HTTP request returns
// now do something with result
}
If you want it to start a background process and return immediately, but for some reason don't want to mark LoadData as async:
public void LoadData() {
BeginLoadData();
}
private async void BeginLoadData() {
var result = await GetBalance();
// now do something with result
}
Though really, there's no reason not to go ahead and make LoadData async. async void does not force you to change the callers in any way (unlike Async<Task<T>>), and it's assignment-compatible with plain old non-async delegates:
public async void LoadData() {
var result = await GetBalance();
// now do something with result
}
// ...
LoadData(); // works just fine
Action myAction = LoadData; // works just fine
As you are working on asynchronus operations you need to wait until the operation is completed.The return type async/await method is always Task(TResult), to access the result of the async/await you need to use Result Property.The get accessor of Result property ensures that the asynchronous operation is complete before returning.
public void LoadData()
{
var data = GetBalance().Result;
}

WCF Calling a service property from a callback without deadlock

Can someone kindly show me how to call a property of a WCF service from within a callback without deadlock occurring?
I've tried adding [CallbackBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)] to the class which implements the callback, but without success.
The service has the following attribute:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]
public class SAPUploadService : ISAPUploadService
{
Thanks MM
Here's the code which calls the Callback method
foreach (var otherConnection in _users.Keys)
{
SAPUploadInstruction ins = AddMessageToInstruction(message);
ins.UserName = user.UserName;
Task.Factory.StartNew(() =>
{
otherConnection.ReceiveInstruction(ins);
});
and here's the callback implementation of the ReceiveInstruction
public void ReceiveInstruction(SAPUploadInstruction instruction)
{
// fire this objects call back....
if (OnReceiveInstruction != null) OnReceiveInstruction(this, instruction);
}
In the above, the event OnReceiveInstruction is attached to the UI. This is handled as follows:
public void ReceiveInstruction(object sender, SAPUploadInstruction instruction)
{
DispatchIfNecessary(() => {
ProcessInstruction(instruction);
});
}
The method above - ProcessInstruction - sets various controls according to the service properties/functions. It is this that is getting deadlocked i.e Label1.Content = myService.SomeProperty.
BTW, DispatchIfNecessary is implemented as :
public void DispatchIfNecessary(Action action)
{
if (!Dispatcher.CheckAccess())
Dispatcher.Invoke(action);
else
action.Invoke();
}
In DispatchIfNecessary use asynchronous version of Invoke, so your callback won't wait for finishing UI changes, that can't be done because UI thread is waiting for end of callback processing (hence we have deadlock):
Dispatcher.BeginInvoke(action);

Categories