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
Inside of one of my methods I have this:

string key = "close";
string script = "<script>...</script>";
((Page)HttpContext.Current.CurrentHandler).ClientScript.RegisterClientScriptBlock(typeof(string),key, script);

It seems complex to me. How could I mock the bold line?

Should I write 5 mock statements for each property or method :(?
HttpContext.Current
HttpContext.Current.CurrentHandler
Page.ClientScript
RegisterClientScriptBlock

Many thanks
asked by Ben (3k points)

11 Answers

0 votes
Hi Ben,

Isolator supports faking call chains so you should be able to do this:
Isolator.WhenCalled(() => ((Page)HttpContext.Current.CurrentHandler).ClientScript.RegisterClientScriptBlock(typeof(string),key, script)).IgnoreCall();


However, a way simpler way of doing this can be done by recursively faking - a recursive fake is a fake that returns a recursive fake for any method called on it. This means the entire call chain will be faked. In your case, you want the static methods of HttpContext to return recursive fakes:
Isolate.Fake.StaticMethods<HttpContext>(Members.ReturnRecursiveFakes);

And the entire chain following HttpContext will be faked.

Let me know if this helps.

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Hi Doron,

Thank you for your response.

I tried the first solution and faced the following error:

failed: System.InvalidCastException: Unable to cast object of type 'Mock0000IHttpHandler' to type 'System.Web.UI.Page'.
at MSTestProject.UtilsTest.<>c__DisplayClass1.<RegisterWindowCloseHelperTest>b__0()

Apparently, TypeMock can't cast IHttpHandler to Page class.

Any thought?
answered by Ben (3k points)
0 votes
The problem with the second approach suggested is that it can't validate that the input parameters have been passed as expected. It just fakes everything.

Ah, also I got the same error with approach 2...
answered by Ben (3k points)
0 votes
I found a solution - I write it for others to benefit

Mocking this in 2 stages:

Func<IHttpHandler> func = delegate() { return HttpContext.Current.CurrentHandler;};
Page myFakedPage = new Page();
Isolate.WhenCalled(func).WillReturn(myFakedPage);

Action action = delegate () { myFakedPage.ClientScript.RegisterClientScriptBlock(typeof (string), key, script); };
Isolate.WhenCalled(action).IgnoreCall();

Then, verifying:
Isolate.Verify.WasCalledWithAnyArguments(func);
Isolate.Verify.WasCalledWithAnyArguments(action);

:)
answered by Ben (3k points)
0 votes
Thanks for the solution - indeed you had to break the chain in two to make sure the casting along the way works, rather than using recursive fakes that auto-generate fakes regardless of type.

Also, you can make the test more readable by using lambda expressions instead of the explicit delegate you used:
Page myFakedPage = new Page(); 
Isolate.WhenCalled(() => HttpContext.Current.CurrentHandler).WillReturn(myFakedPage); 

Isolate.WhenCalled(() => myFakedPage.ClientScript.RegisterClientScriptBlock(typeof (string), key, script)).IgnoreCall(); 


Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Looking at the code again, you can compact it further by using a recursive fake instead of the page - it doesn't go through the casting that caused you from using that technique with HttpContext:
var fakePage = Isolate.Fake.Instance<Page>(); // creates recursive fake
Isolate.WhenCalled(() => HttpContext.Current.CurrentHandler).WillReturn(fakePage); 


The second WhenCalled() is not needed now because the recursive fake takes care of ignoring the call for you.

Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Thank you for the suggestions Doron.

But for my scenario I don't think I can compact my codes further because:

1. Unfortunately, I am using .NET 2.0 so can't use Lambda expressions
2. I need to store the contents of WhenCalled() in a seperate variable so that I can pass that variable to my Isolate.Verify.WasCalledWithExactArguments(action); (To remove duplication)
3. I need to verify that the arguments passed are exactly the key and script (these two are calculated in the production code and are indeed expectedKey and expectedValue)

Thanks
answered by Ben (3k points)
0 votes
These reasons are all valid. I personally prefer using lambda expressions (unless of course I'm working in .net 2.0) when possible. Note that the arguments you put in the WhenCalled() statement are disregarded* and only those in Verify.WasCalledWithExactArguments matter.

* that is until we implement conditional behavior - right around the corner now

Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Slightly off topic...

But for web testing would Ivonna (Typemock add-on) handle this situation?
answered by boo (21.8k points)
0 votes
Brian,

Ivonna's built on top of Isolator's engine, so it has the same capabilities. I'll ask Artem (Ivonna's author) to answer this with more details.
answered by gilz (14.5k points)
...