Using callback triggers with RhinoMocks - c#

I'm writing unit tests using RhinoMocks for mocking, and now I'm in need of some new functionality which I haven't used before.
I'd like to call a function, which again will call an async function. To simulate that the async function finishes and triggers the given callback with the result from execution I assume I can use the Callback functionality in RhinoMocks, but how do I do this?
Basically what I'd like to do is something like this:
fakeSomething = MockRepository.GenerateMock<ISomething>();
fakeSomething.FictionousFunctionSettingCallback(MyFunctionCalled, MyCallback, theParameterToGiveCallback);
var myObj = new MyClass(fakeSomething);
myObj.Foo();
// Foo() now fires the function MyFunctionCalled asynchronous,
// and eventually would trigger some callback
So; is there a true function I can replace this "FictionousFunction" with to set this up? Please ask if this was unclear..

Just specify it using WhenCalled:
fakeSomething = MockRepository.GenerateMock<ISomething>();
fakeSomething
.Stub(x => x.Foo())
.WhenCalled(call => /* do whatever you want */);
for instance, you can use the Arguments property of the call argument:
fakeSomething
.Stub(x => x.Foo(Arg<int>.Is.Anything))
.WhenCalled(call =>
{
int myArg = (int)call.Arguments[0]; // first arg is an int
DoStuff(myArg);
});
It is not asynchronous. You most probably don't need it to be asynchronous, it makes your life easier anyway if it isn't.

Related

Is there a way to take a synchronous method that may or may not return a value and add it to a List<Func<Task>>?

In the process of refactoring some legacy code at work and part of it is to convert an instance of List<Action> to List<Func<Task>>. Elsewhere in the codebase, there are several instances of something along the lines of this:
entity.Tasks.Add(() =>
{
_service.Process(operation)
}
The above would work fine when the Tasks property was List<Action>, but gives errors when turned into List<Func<Task>> with no obvious way to fix it.
I know next to nothing about Func, Task, Action, asynchronous/synchronous programming, particularly in C#. Any help provided is immensely appreciated or even just a referral to information where I could find the information needed to solve this myself.
What you have to do is to create a function that returns a Task. A solution could be creating a task that internally executes your synchronous code and then add it to the list. Like this:
entity.Tasks.Add(() => Task.Run(_service.Process(operation)));
Just note that the code only creates a function that returns a Task but the Task won't be executed until you ask for it.
Here is more info about the topic:
Task.Run Method
Task-based Asynchronous Programming in C#
A quick primer...
List<Action> says: I'm a list that accepts a method with no input parameters and returns void when invoked.
List<Func<Task>> says: I'm a list that accepts a method with no input parameters and returns a Task when invoked.
Note: I'm using the term "method" to represent a named method, delegate, lambda, etc...
For your case, entity.Tasks was originally defined as List<Action>; but is now defined as List<Func<Task>>.
Given the case where you need to take the legacy methods which return no value (void), you could create a shimming method which returns a task after completing the Action from the original method.
For Example...
static Task Shim( Action action )
{
action();
return Task.CompletedTask;
}
// the above will wrap a method that does not return a value such as:
static void DoWork( string str )
{
Debug.WriteLine( str );
}
You can now use the Shim to add to your new collection type. For example...
var list = new List<Func<Task>>();
// add the Shim to the list
list.Add( () => Shim( () => DoWork( "I'm a shim" ) ));
In your use case, it will look something like this:
entity.Tasks.Add(() =>
{
return Shim( () => _service.Process(operation) );
}
// or a bit more shorthanded:
entity.Tasks.Add( () => Shim( () => _service.Process(operation) ));
As pointed out in the comments, the Shim path is less than ideal since the new version really should be wrapped in a Task to be more inline with how Tasks and Exceptions get wrapped up.
Here's an example of wrapping the legacy code into the new version without any shims:
entity.Tasks.Add( () => Task.Run( () => _service.Process(operation) ));
Actions are your void methods that don't return a response. Your tasks collection is expecting a returned task. You can wrap the _service.Process(operation) with a task and within the task, run the _service.Process, then return something like
return Task.FromResult(false);

How do you access the number of times a delegate has been called?

I am currently writing a test for a piece of functionality. I need to count how many times an event handler has been called. In this example I want to ensure the delegate 'failureHandler' is never called.
I have achieved what I want from a test perspective by doing an Assert.Fail() if it is called. What I want do though is count the number of times a delegate is called for use in other parts of the test.
I believe I read somewhere you could access this information via property but I can't remember where I read it!
Action failureHandler =
completed => Assert.Fail("Not all tasks have been completed");
_testObj.TaskCompletedForItems += failureHandler;
You can use MOQ, and verify how many times the action has been invoked:
Mock<Action> mockAction = new Mock<Action>();
Action action = mockAction.Object;
//call action
action();
//verify that it was never called
mockAction.Verify(act => act(), Times.Never());
//or verify that it has been called exactly once
mockAction.Verify(act => act(), Times.Once());
No, there's no standard property for that... but you can easily use the fact that a lambda expression is a closure to emulate it:
int callCount = 0;
Action handler = () => callCount++;
_testObj.TaskCompletedForItems += handler;
// Do stuff
Assert.AreEqual(expectedCount, callCount);

c# simple background thread

I am looking for a simple way to do a task in background, then update something (on the main thread) when it completes. It's in a low level 'model' class so I can't call InvokeOnMainThread as I don't have an NSObject around. I have this method:
public void GetItemsAsync(Action<Item[]> handleResult)
{
Item[] items=null;
Task task=Task.Factory.StartNew(() =>
{
items=this.CreateItems(); // May take a second or two
});
task.ContinueWith(delegate
{
handleResult(items);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
This seems to work OK, but
1) Is this the best (simplest) way?
2) I'm worried about the local variable:
Item{} items=null
What stops that disappearing when the method returns before the background thread completes?
Thanks.
I think your method slightly violates a Single Responsibility Principle, because it doing too much.
First of all I suggest to change CreateItems to return Task instead of wrapping it in the GetItemsAsync:
public Task<Item[]> CreateItems(CancellationToken token)
{
return Task.Factory.StartNew(() =>
// obtaining the data...
{});
}
CancellationToken is optional but can help you if you able to cancel this long running operation.
With this method you can remove GetItemsAsync entirely because its so simple to handle results by your client without passing this delegate:
// Somewhere in the client of your class
var task = yourClass.CreateItems(token);
task.ContinueWith(t =>
// Code of the delegate that previously
// passed to GetItemsAsync method
{}, TaskScheduler.FromCurrentSynchronizationContext());
Using this approach you'll get more clear code with only one responsibility. Task class itself is a perfect tool for representing asynchronous operation as a first class object. Using proposed technique you can easily mock you current implementation with a fake behavior for unit testing without changing your clients code.
Something like this:
public void GetItemsAsync(Action<Item[]> handleResult)
{
int Id = 11;
Task<Item[]> task = Task.Factory.StartNew(() => CreateItems(Id)); // May take a second or two
task.ContinueWith(t => handleResult(t.Result), TaskScheduler.FromCurrentSynchronizationContext());
}
Your code looks fine.
It's a perfect example of when to use async / await if you can use C# 5, but if not, you have to write it as you have done with continuations.
The items variable is captured in your lambdas, so that's fine too.
When you write a lambda that uses an outside variable, the C# compiler creates a class that contains the variable. This is called a closure and means you can access the variable inside your lambda.
Here is a nicer soultion:
public void GetItemsAsync(Action<Item[]> handleResult)
{
var task = Task.Factory.StartNew<Item[]>(() =>
{
return this.CreateItems(); // May take a second or two
});
task.ContinueWith(delegate
{
handleResult(task.Result);
}, TaskScheduler.FromCurrentSynchronizationContext());
}

need help accessing data coming off a callback C# .NET

I'm at my wits end trying to solve this issue.
I have a function in a class as such
public class ReceiveData
{
Dataprovider provider = new DataProvider();
public void ResponseData()
{
foreach(string anItem in TheList)
{
// AllData function is declared in class DataProvider
string result = provider.AllData(anItem);
}
//do something
}
}
That's simple. However, what would I do if AllData function had to make async function calls to get data?
Meaning, say
public class DataProvider
{
MyServiceClient client = new MyServiceClient();
public string AllData (string myItem)
{
client.FormattedDataCompleted += new EventHandler<FormattedDataCompletedEventArgs>(client_FormattedDataCompleted);
client.FormattedDataAsync(myItem);
}
void client_FormattedDataCompleted(object sender, FormattedDataCompletedEventArgs e)
{
// here's where the response comes back.
}
As you can see, now I cant simply call AllData function and directly get data back.
So, what would I have to do in ResponseData function to make sure I call the AllItem function, and get data back from the callback. Notice that there's a loop in that function, so I need to all the parameters I have sent through the loop gets respective response.
One approach I tried was by using AutoResetEvent class.
I defined a handler for this as
AutoResetEvent handle = new AutoResetHandle(false);
then I add handle.WaitOne() right after the async call. and on the callback, added handle.Set();
However, the applications get stuck at handle.WaitOne(). So I can't really see why that happens.
I now have a theoritical idea to see if I could have a event raiser on the callback, and an eventlistener in RecieveData class, and if those two communicate, I could get the data. But I've spent some time trying to learn more about event handlers, but haven't gotten the hang of it.
So does anybody have any other approach, ideas? Thanks!
Welcome to the asynchronous model. You have to re-think how you call methods when you go multithreaded.
You have some options:
Split the method in which you're making the call into two halves; in the first half, call AllData, do ANYTHING else you can possibly do without having the response object, and then exit your current method. When the async call completes, it'll call your handler, where you should perform all operations from the original method that require the response.
In the event handler for the async call completion, set a property that indicates the call is completed, and put the data out on a property somewhere as well. In the function that kicks off the call, at the point where you simply cannot continue execution until the call completes, wait in a while loop for the call to complete by polling the property and breaking once it indicates the call has been completed (you'll probably want a Thread.Yield() in the loop as well that you'll call when you haven't gotten a response yet, to make sure you aren't blocking other threads doing more important things than waiting)
Wrap your asynchronous call in a class that exposes a synchronous method. The wrapper class will have similar logic as integrating the async call into your method. It will make the call, wait for the response, and return that response as if it were a normal synchronous method call.
Remember that the asynchronous call is giving your calling thread the opportunity to do other work while the call is performed. Take full advantage of this if at all possible.
You just need to use a delegate and call BeginInvoke. You can then set a callback method to capture the result of the delegate call.
public class ReceiveData
{
private List<string> TheList = new List<string>
{
"1", "2", "3"
};
dynamic provider = new ExpandoObject();
public void ResponseData()
{
foreach (string anItem in TheList)
{
// AllData function is declared in class DataProvider
Func<string, string> asyncAllData = provider.AllData;
asyncAllData.BeginInvoke(anItem, AllDataDone, null);
}
//do something
}
private void AllDataDone(IAsyncResult iar)
{
AsyncResult ar = (AsyncResult)iar;
var del = (Func<string, string>)ar.AsyncDelegate;
// here's your result
string result = del.EndInvoke(iar);
}
}

Unit testing methods with a local Thread

I have a method that looks like this:
protected void OnBarcodeScan(BarcodeScannerEventArgs e)
{
// We need to do this on a seperate thread so we don't block the main thread.
ThreadStart starter = () => SendScanMessage(e, _scanDelegates);
Thread scanThread = new Thread(starter);
scanThread.Start();
}
Then the thread goes off and does some logic (and ends up calling a delegate in my test).
My problem is that my unit test finishes before the thread does. So my test fails.
I can just add in System.Threading.Thread.Sleep(1000); and hope that the logic never takes more than a second (it should not). But that seems like a hack.
The problem is that I don't want to expose that thread to the outside world or even to the rest of the class.
Is there some cool way to find that thread again and wait for it in my unit test?
Something like this:
[TestMethod]
[HostType("Moles")]
public void AddDelegateToScanner_ScanHappens_ScanDelegateIsCalled()
{
// Arrange
bool scanCalled = false;
MCoreDLL.GetTopWindow = () => (new IntPtr(FauxHandle));
// Act
_scanner.AddDelegateToScanner(_formIdentity, ((evnt) => { scanCalled = true; }));
_scanner.SendScan(new BarcodeScannerEventArgs("12345678910"));
// This line is fake!
System.Threading.Thread.CoolMethodToFindMyThread().Join();
// Assert
Assert.IsTrue(scanCalled);
}
I obviously made up the CoolMethodToFindMyThread method. But is there some why to do that?
So if I understand how this works, then the delegates you register are the ones being called on the second thread, right? In that case, you can use thread synchronization in your test and the delegate that gets called. I do this kind of thing in my unit tests all the time.
Something like this:
[TestMethod]
[HostType("Moles")]
public void AddDelegateToScanner_ScanHappens_ScanDelegateIsCalled()
{
// Arrange
var scanCalledEvent = new ManualResetEvent(false);
MCoreDLL.GetTopWindow = () => (new IntPtr(FauxHandle));
// Act
_scanner.AddDelegateToScanner(_formIdentity, ((evnt) => { scanCalledEvent.Set(); }));
_scanner.SendScan(new BarcodeScannerEventArgs("12345678910"));
// Wait for event to fire
bool scanCalledInTime = scanCalledEvent.WaitOne(SOME_TIMEOUT_IN_MILLISECONDS);
// Assert
Assert.IsTrue(scanCalledInTime);
}
It's important to have some sort of timeout in there, otherwise if something goes wrong your test just locks up and that's kind of hard to debug. WaitOne will block until the event gets set or the timeout expires, the return value tells you which happened.
(WARNING: I may have the return value backwards - I don't remember off the top of my head if true means the event got set or if true means the timeout expired. Check the docs.)
There are several sync primitives you can use here, which one depends on what you want to do. ManualResetEvent usually works pretty well for me.
There's another way of doing things:
First, have an AutoResetEvent (or ManualResetEvent, if you feel like) in your test class.
In your test method:
//set up stuff
testEvent.WaitOne();
//ensure everything works
In your callback
testEvent.Set();
Your test method will then stop until the callback gets called.
Presumably you'll want some sort of timeout on that wait call as well.

Categories

Resources