chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
The codebase I’m testing is making an extensive usage of the async pattern (BeginXXX, EndXXX).
Mocking async operations is somewhat cumbersome with the AAA API.

For the code flow to be appropriately faked, the BeginXXX must call the callback. Otherwise the test will hang if the code under test perform calls such as:
action.BeginXXX(paramA, result =>
{        
    action.EndXXX(result);
    completedEvent.Set();
}, null);

What I’m currently doing is creating a mock object for each object that makes use of the async pattern.
Then I use the Isolate.Swap to fake calls on the original object:
Isolate.Swap.CallsOn(originalObject).WithCallsTo(fakedObject);

Each mock looks the same:

private Action m_action = () => { };

public IAsyncResult BeginXXX(String parameterA, HttpListenerContext context,
    AsyncCallback callback, object asyncState)
{
    return m_action.BeginInvoke(callback, asyncState);
}

public void EndXXX(IAsyncResult asyncResult)
{
    m_action.EndInvoke(asyncResult);
}

Is there an easier way to do this? Maybe the previous generation API?
It could have been cool if Isolater could inspect method signatures of faked objects and automatically inject the code above.

Thanks,
Noam
asked by NoamK (1.1k points)

4 Answers

0 votes
Hi Noam

Not sure I understand what you want to do here
Do you want to fake the callbacks methods?

In that case we have a feature in the upcoming release this week that might solve the problem.
The feature allows you to specify your own delegate that will run when a faked method gets called.

For example:
Isolate.WhenCalled(() => fake.BeginXXX(arg1, arg2)).DoInstead((callContext) =>
                                                    {
                                                       // callContext has the context and the method argument
                                                        // code that will run when BeginXXX is called
                                                    });



Please tell me if it helps.
answered by ohad (35.5k points)
0 votes
Hi Ohad,

I wanted to fake an object that exposes async operations, a System.IO.Stream for example.
The DoInstead feature makes it easier to correctly fake the async pattern:

Func<int> pseudoAction = () => { return 0; };
Isolate.WhenCalled(() => fakeStream.BeginRead(null, 0, 0, null, null)).DoInstead((callContext) =>
{
    return pseudoAction.BeginInvoke(callContext.callback, callContext.state);
    // Or: return pseudoAction.BeginInvoke(callContext.Args[3], callContext.Args[4]); 
});
Isolate.WhenCalled(() => fakeStream.EndRead(null)).DoInstead((callContext) =>
{
    pseudoAction.EndInvoke(callContext.asyncResult);
    // Or: pseudoAction.EndInvoke(callContext.Args[0]);
});

(or simply invoke the callback synchrnously on fakeStream.BeginRead)

If the code under test is something like the code below, then the default recursive fake object is not enough.
The faked Stream object must invoke the callback for the test to pass.

public bool DoSomething(Stream stream)
{
    bool success = false;
    var completedEvent = new AutoResetEvent(false);
    
    stream.BeginRead(buffer, offset, count, result =>
    {
        int readBytes = stream.EndRead(result);
        success = readBytes == count;
        completedEvent.Set();
    }, null);

    // Do something else...

    completedEvent.WaitOne();
    return success;
} 


I would like to suggest that Isolate.Fake.Instance will automatically detect the async pattern, and the default faked object will invoke the callback on BeginXXX.

Thanks a lot,
Noam
answered by NoamK (1.1k points)
0 votes
Hi,

We've built a similar example to what you're trying to do. . But let's take it offline, and take it from there. I'll contact you via email.

Thanks,
answered by gilz (14.5k points)
0 votes
:idea: An example of working with threads and asynchronous operations might be a good set of examples to put under 'Learn/Users Guide' for the next person who runs into the question of 'how should I' when it comes to that...
answered by boo (21.8k points)
...