<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Testing</title>
        <link>http://ridgway.co.za/category/16.aspx</link>
        <description>Posts related to software testing.</description>
        <language>en-ZA</language>
        <copyright>Eden Ridgway</copyright>
        <managingEditor>eden@ridgway.co.za</managingEditor>
        <generator>Subtext Version 1.9.5.176</generator>
        <item>
            <title>Using Synchronous ASP.Net AJAX Web Service Calls and Scriptaculous to Test your JavaScript</title>
            <link>http://ridgway.co.za/archive/2007/10/30/using-synchronous-asp.net-ajax-web-service-calls-and-scriptaculous-to.aspx</link>
            <description>As our web applications become more JavaScript heavy it is becomes increasingly important that we have tests for this code. In the past I have managed to get away with it but in retrospect it was a risky approach to take. So in my latest project I started assessing the various JavaScript unit testing frameworks and decided &lt;a href="http://wiki.script.aculo.us/scriptaculous/show/UnitTesting" target="_blank"&gt;Scriptaculous&lt;/a&gt; was the way to go. I excluded &lt;a href="http://www.jsunit.net/" target="_blank"&gt;JsUnit&lt;/a&gt; as an option because it is not object oriented and didn't give me enough information about which tests had passed. The Scriptaculous unit testing framework also has some useful features like the ability to wait before completing the test and benchmarking of calls.&lt;br /&gt;
&lt;br /&gt;
The one big problem you have when testing an AJAX application however is that the out-of-band calls are made asynchronously. This means that if you are testing a method that does a load and want to ensure that certain values are set or calls made once the data has loaded you have to have a bit of a problem. The Scriptaculous framework's solution to this  is the ability to wait and execute a function that may then contain your asserts. Here is a basic example of what the test would look like:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt; &lt;font color="blue"&gt;new &lt;/font&gt;&lt;font color="black"&gt;Test.Unit.Runner(&lt;br /&gt;
{&lt;br /&gt;
    testShouldLoadDataOnInit: &lt;/font&gt;&lt;font color="blue"&gt;function&lt;/font&gt;&lt;font color="black"&gt;() &lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;manager &lt;/font&gt;&lt;font color="blue"&gt;= new &lt;/font&gt;&lt;font color="black"&gt;TestManager()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//This makes a web service call&lt;/font&gt;&lt;br /&gt;
&lt;font color="blue"&gt;         &lt;/font&gt;&lt;font color="black"&gt;manager.onInit()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;br /&gt;
        this&lt;/font&gt;&lt;font color="black"&gt;.wait(&lt;/font&gt;&lt;font color="maroon"&gt;500&lt;/font&gt;&lt;font color="black"&gt;, &lt;/font&gt;&lt;font color="blue"&gt;function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
                       {&lt;br /&gt;
                          &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.assertNotEqual(manager._TestData, &lt;/font&gt;&lt;font color="blue"&gt;null&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
                       &lt;/font&gt;&lt;font color="black"&gt;})&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;},&lt;br /&gt;
})&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
I found that this led to inconsistent test results because for various reasons the webservice request callbacks would take a varying amount of time. Of course you could try to cover yourself by making the wait time larger but then your tests take too long to run. Both of these problems will discourage others from using and extending your tests.&lt;br /&gt;
&lt;br /&gt;
Having hand coded XMLHTTP calls in the days before the approach was known as AJAX I knew that it was possible to make the calls synchronously, so all I needed to do was get the generated ASP.Net AJAX webservice  proxies to use a new synchronous  executor. I came across &lt;a href="http://geekswithblogs.net/rashid/archive/2007/07/04/SJAX-Call.aspx" target="_blank"&gt;Amit's SJAX post&lt;/a&gt; that demonstrated how to created a synchronous executor for a Sys.Net.WebRequest object which was very useful. I discovered that one could change the executor for generated webservice proxy calls by changing the default executor type for the Sys.Net.WebRequestManager, like so:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt; &lt;font color="black"&gt;Sys.Net.WebRequestManager.set_defaultExecutorType(&lt;/font&gt;&lt;font color="#808080"&gt;"Example.Executor"&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
So I took Amit's example, changed it somewhat and got it to work work as a synchronous request handler (using the debug version of the ASP.Net AJAX framework JavaScript as a guide). This resulted in a handler that looked like this (note I have removed code and replaced them with comments for brevity) [&lt;a href="http://www.ridgway.co.za/demos/XMLHttpSyncExecutor.zip"&gt;download full file here&lt;/a&gt;]:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt; &lt;font color="black"&gt;Type.registerNamespace(&lt;/font&gt;&lt;font color="#808080"&gt;'Sjax'&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;font color="black"&gt;Sjax.XMLHttpSyncExecutor &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
{&lt;br /&gt;
    Sjax.XMLHttpSyncExecutor.initializeBase(&lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
    this&lt;/font&gt;&lt;font color="black"&gt;._started &lt;/font&gt;&lt;font color="blue"&gt;= false;&lt;br /&gt;
    this&lt;/font&gt;&lt;font color="black"&gt;._responseAvailable &lt;/font&gt;&lt;font color="blue"&gt;= false;&lt;br /&gt;
    this&lt;/font&gt;&lt;font color="black"&gt;._onReceiveHandler &lt;/font&gt;&lt;font color="blue"&gt;= null;&lt;br /&gt;
    this&lt;/font&gt;&lt;font color="black"&gt;._xmlHttpRequest &lt;/font&gt;&lt;font color="blue"&gt;= null;&lt;br /&gt;
    &lt;br /&gt;
    this&lt;/font&gt;&lt;font color="black"&gt;.get_aborted &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;return false;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.get_responseAvailable &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;return this&lt;/font&gt;&lt;font color="black"&gt;._responseAvailable&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.get_responseData &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;return this&lt;/font&gt;&lt;font color="black"&gt;._xmlHttpRequest.responseText&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.get_started &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;return this&lt;/font&gt;&lt;font color="black"&gt;._started&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.get_statusCode &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;return this&lt;/font&gt;&lt;font color="black"&gt;._xmlHttpRequest.status&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.get_statusText &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;return this&lt;/font&gt;&lt;font color="black"&gt;._xmlHttpRequest.statusText&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.get_xml &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Code removed&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.executeRequest &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;webRequest &lt;/font&gt;&lt;font color="blue"&gt;= this&lt;/font&gt;&lt;font color="black"&gt;.get_webRequest()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
        if &lt;/font&gt;&lt;font color="black"&gt;(webRequest &lt;/font&gt;&lt;font color="blue"&gt;=== null&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
        {&lt;br /&gt;
            &lt;/font&gt;&lt;font color="blue"&gt;throw &lt;/font&gt;&lt;font color="black"&gt;Error.invalidOperation(Sys.Res.nullWebRequest)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;body &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;webRequest.get_body()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        var &lt;/font&gt;&lt;font color="black"&gt;headers &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;webRequest.get_headers()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        var &lt;/font&gt;&lt;font color="black"&gt;verb &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;webRequest.get_httpVerb()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
        var &lt;/font&gt;&lt;font color="black"&gt;xmlHttpRequest &lt;/font&gt;&lt;font color="blue"&gt;= new &lt;/font&gt;&lt;font color="black"&gt;XMLHttpRequest()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        this&lt;/font&gt;&lt;font color="black"&gt;._onReceiveHandler &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;Function.createCallback(&lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;._onReadyStateChange, { sender:&lt;/font&gt;&lt;font color="blue"&gt;this &lt;/font&gt;&lt;font color="black"&gt;})&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        this&lt;/font&gt;&lt;font color="black"&gt;._started &lt;/font&gt;&lt;font color="blue"&gt;= true;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;xmlHttpRequest.onreadystatechange &lt;/font&gt;&lt;font color="blue"&gt;= this&lt;/font&gt;&lt;font color="black"&gt;._onReceiveHandler&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;xmlHttpRequest.open(verb, webRequest.getResolvedUrl(), &lt;/font&gt;&lt;font color="blue"&gt;false&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;; &lt;/font&gt;&lt;font color="darkgreen"&gt;// False to call Synchronously&lt;br /&gt;
&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;if &lt;/font&gt;&lt;font color="black"&gt;(headers)&lt;br /&gt;
        {&lt;br /&gt;
            &lt;/font&gt;&lt;font color="blue"&gt;for &lt;/font&gt;&lt;font color="black"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;header &lt;/font&gt;&lt;font color="blue"&gt;in &lt;/font&gt;&lt;font color="black"&gt;headers)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;val &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;headers[header]&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
&lt;br /&gt;
                if &lt;/font&gt;&lt;font color="black"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;typeof&lt;/font&gt;&lt;font color="black"&gt;(val) !&lt;/font&gt;&lt;font color="blue"&gt;== &lt;/font&gt;&lt;font color="#808080"&gt;"function"&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
                {&lt;br /&gt;
                    xmlHttpRequest.setRequestHeader(header, val)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
                &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;if &lt;/font&gt;&lt;font color="black"&gt;(verb.toLowerCase() &lt;/font&gt;&lt;font color="blue"&gt;=== &lt;/font&gt;&lt;font color="#808080"&gt;"post"&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
        {&lt;br /&gt;
            &lt;/font&gt;&lt;font color="blue"&gt;if &lt;/font&gt;&lt;font color="black"&gt;((headers &lt;/font&gt;&lt;font color="blue"&gt;=== null&lt;/font&gt;&lt;font color="black"&gt;) || !headers[&lt;/font&gt;&lt;font color="#808080"&gt;'Content-Type'&lt;/font&gt;&lt;font color="black"&gt;])&lt;br /&gt;
            {&lt;br /&gt;
                xmlHttpRequest.setRequestHeader(&lt;/font&gt;&lt;font color="#808080"&gt;'Content-Type'&lt;/font&gt;&lt;font color="black"&gt;, &lt;/font&gt;&lt;font color="#808080"&gt;'application/x-www-form-urlencoded'&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
            &lt;/font&gt;&lt;font color="blue"&gt;if &lt;/font&gt;&lt;font color="black"&gt;(!body)&lt;br /&gt;
            {&lt;br /&gt;
                body &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="#808080"&gt;''&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;._started &lt;/font&gt;&lt;font color="blue"&gt;= true;&lt;br /&gt;
        this&lt;/font&gt;&lt;font color="black"&gt;._xmlHttpRequest &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;xmlHttpRequest&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;xmlHttpRequest.send(body)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.getAllResponseHeaders &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;()&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;return this&lt;/font&gt;&lt;font color="black"&gt;._xmlHttpRequest.getAllResponseHeaders()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;.getResponseHeader &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;(header)&lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="darkgreen"&gt;//Parameter validation code removed here...&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;return this&lt;/font&gt;&lt;font color="black"&gt;._xmlHttpRequest.getResponseHeader(header)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    &lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;this&lt;/font&gt;&lt;font color="black"&gt;._onReadyStateChange &lt;/font&gt;&lt;font color="blue"&gt;= function&lt;/font&gt;&lt;font color="black"&gt;(e)&lt;br /&gt;
    {  &lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;executor &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;e.sender&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
            &lt;br /&gt;
        if &lt;/font&gt;&lt;font color="black"&gt;(executor._xmlHttpRequest.readyState &lt;/font&gt;&lt;font color="blue"&gt;=== &lt;/font&gt;&lt;font color="maroon"&gt;4&lt;/font&gt;&lt;font color="black"&gt;)&lt;br /&gt;
        {&lt;br /&gt;
            &lt;/font&gt;&lt;font color="darkgreen"&gt;//Validation code removed here...&lt;br /&gt;
&lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;executor._responseAvailable &lt;/font&gt;&lt;font color="blue"&gt;= true;&lt;br /&gt;
&lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;executor._xmlHttpRequest.onreadystatechange &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;Function.emptyMethod&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;executor._onReceiveHandler &lt;/font&gt;&lt;font color="blue"&gt;= null;&lt;br /&gt;
&lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;executor._started &lt;/font&gt;&lt;font color="blue"&gt;= false;&lt;br /&gt;
            &lt;br /&gt;
            var &lt;/font&gt;&lt;font color="black"&gt;webRequest &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;executor.get_webRequest()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;webRequest.completed(Sys.EventArgs.Empty)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
            &lt;br /&gt;
            &lt;/font&gt;&lt;font color="darkgreen"&gt;//Once the completed callback handler has processed the data it needs from the XML HTTP request we can clean up&lt;br /&gt;
            &lt;/font&gt;&lt;font color="black"&gt;executor._xmlHttpRequest &lt;/font&gt;&lt;font color="blue"&gt;= null;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Sjax.XMLHttpSyncExecutor.registerClass(&lt;/font&gt;&lt;font color="#808080"&gt;'Sjax.XMLHttpSyncExecutor'&lt;/font&gt;&lt;font color="black"&gt;, Sys.Net.WebRequestExecutor)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
So now we can create tests that test objects that make synchronous webservice calls by changing the default executor in the setup of the unit test like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt; &lt;font color="blue"&gt;new &lt;/font&gt;&lt;font color="black"&gt;Test.Unit.Runner(&lt;br /&gt;
{&lt;br /&gt;
    setup: &lt;/font&gt;&lt;font color="blue"&gt;function&lt;/font&gt;&lt;font color="black"&gt;() &lt;br /&gt;
    { &lt;br /&gt;
        Sys.Net.WebRequestManager.set_defaultExecutorType(&lt;/font&gt;&lt;font color="#808080"&gt;"Sjax.XMLHttpSyncExecutor"&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;},&lt;br /&gt;
&lt;br /&gt;
    testShouldLoadDataOnInit: &lt;/font&gt;&lt;font color="blue"&gt;function&lt;/font&gt;&lt;font color="black"&gt;() &lt;br /&gt;
    {&lt;br /&gt;
        &lt;/font&gt;&lt;font color="blue"&gt;var &lt;/font&gt;&lt;font color="black"&gt;manager &lt;/font&gt;&lt;font color="blue"&gt;= new &lt;/font&gt;&lt;font color="black"&gt;TestManager()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;/font&gt;&lt;font color="black"&gt;manager.onInit()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
        &lt;br /&gt;
        this&lt;/font&gt;&lt;font color="black"&gt;.assertNotEqual(manager._TestData, &lt;/font&gt;&lt;font color="blue"&gt;null&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;},&lt;br /&gt;
})&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt; 	&lt;/div&gt;
&lt;br /&gt;
I think you'll agree that with the extensibility they have provided in the ASP.Net AJAX framework, what we have now is quite a neat way of ensuring that our tests run consistently and as fast as they can. My thanks go out to Microsoft and the Scriptaculous team! :)&lt;img src="http://ridgway.co.za/aggbug/188.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Eden Ridgway</dc:creator>
            <guid>http://ridgway.co.za/archive/2007/10/30/using-synchronous-asp.net-ajax-web-service-calls-and-scriptaculous-to.aspx</guid>
            <pubDate>Tue, 30 Oct 2007 06:17:07 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2007/10/30/using-synchronous-asp.net-ajax-web-service-calls-and-scriptaculous-to.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/188.aspx</wfw:commentRss>
        </item>
        <item>
            <title>WatiN - A .Net IE Testing Framework</title>
            <link>http://ridgway.co.za/archive/2007/01/11/177.aspx</link>
            <description>Today I discovered &lt;a href="http://watin.sourceforge.net" target="_blank"&gt;WatiN&lt;/a&gt; which is a &lt;a href="http://www.openqa.org/watir/"&gt;Watir&lt;/a&gt; inspired testing framework for .Net that automates Internet Explorer actions.  Here are some of the more notable features of the framework:&lt;br /&gt;
&lt;ul&gt;
    &lt;li&gt;Support for frames (cross domain) and iframes&lt;/li&gt;
    &lt;li&gt;Support for popup dialogs like alert, confirm, login etc.&lt;/li&gt;
    &lt;li&gt;Support for HTML dialogs (modal and modeless)&lt;/li&gt;
    &lt;li&gt;Supports AJAX website testing.&lt;/li&gt;
    &lt;li&gt;Works with Internet Explorer 6 and Internet Explorer 7&lt;/li&gt;
&lt;/ul&gt;
The WatiN site has pretty good documentation documentation to get you started.  Furthermore Richard Griffin ported the &lt;a href="http://www.hanselman.com/blog/NewReleaseOfWatirMakerNowWatirRecorder.aspx" target="_blank"&gt;WATiR WebRecorder++&lt;/a&gt; to create &lt;a href="http://blogs.conchango.com/richardgriffin/archive/2006/10/18/WATiN-web-recorder_2B002B00_-prototype.aspx" target="_blank"&gt;WATiN WebRecorder++&lt;/a&gt; so there is a quick way of creating initial test scripts.  Richard also has some &lt;a href="http://blogs.conchango.com/richardgriffin/archive/2006/11/14/Testing-Design-Pattern-for-using-WATiR_2F00_N.aspx"&gt;great advice&lt;/a&gt; on test case design which I'm going to get my team to read.&lt;br /&gt;
&lt;br /&gt;
This may be just what I've been looking for to promote more automated web testing at my current company &lt;img alt="" src="/Providers/BlogEntryEditor/FCKeditor/editor/images/smiley/msn/teeth_smile.gif" /&gt;.&lt;img src="http://ridgway.co.za/aggbug/177.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Eden Ridgway</dc:creator>
            <guid>http://ridgway.co.za/archive/2007/01/11/177.aspx</guid>
            <pubDate>Thu, 11 Jan 2007 04:20:30 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2007/01/11/177.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/177.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Acceptance Testing - Fit</title>
            <link>http://ridgway.co.za/archive/2005/07/16/acceptancetestingfit.aspx</link>
            <description>&lt;p&gt; Before I delve into the technical details of test first development, I would like to discuss something that I came across today, a &lt;a href="http://fit.c2.com/"&gt;Framework for Integrated Testing&lt;/a&gt; (FIT).  This really falls in the User Acceptance Testing category.  The idea behind fit is that you can get customers (or BAs) to give you documentation in a tabular format that can be used for unit testing.  Given that most people are familiar with and comfortable with working with tables in Excel and Word you can get them to put down the requirements in a format that they understand but is also useful for testing.  A FIT document may look like the one below: &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table cellspacing="0" cellpadding="3" border="1" align="center"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td colspan="3"&gt; &lt;font size="2"&gt;eg.Division &lt;/font&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt; &lt;font size="2"&gt;numerator &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;denominator &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;quotient() &lt;/font&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt; &lt;font size="2"&gt;1000 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;10 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;100.0000 &lt;/font&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt; &lt;font size="2"&gt;-1000 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;10 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;-100.0000 &lt;/font&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt; &lt;font size="2"&gt;1000 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;7 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;142.85715 &lt;/font&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt; &lt;font size="2"&gt;1000 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;.00001 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;100000000 &lt;/font&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt; &lt;font size="2"&gt;4195835 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;3145729 &lt;/font&gt;&lt;/td&gt;
            &lt;td&gt; &lt;font size="2"&gt;1.3338196 &lt;/font&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; The way FIT works is to look at an HTML table (possible exported from a MS Office product) and using that as a test fixture.  A developer may have to do the actual test mapping, but the idea is that both the input and the output will be in a format understandable by normal users.  This is what the test fixture for the above test would look like: &lt;/p&gt;
&lt;div class="code"&gt;&lt;font color="blue"&gt;public class &lt;/font&gt;&lt;font color="black"&gt;Division : ColumnFixture &lt;br /&gt;
{&lt;br /&gt;
    &lt;/font&gt;&lt;font color="blue"&gt;public float &lt;/font&gt;&lt;font color="black"&gt;numerator&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    public float &lt;/font&gt;&lt;font color="black"&gt;denominator&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    public float &lt;/font&gt;&lt;font color="black"&gt;quotient()&lt;br /&gt;
    {&lt;br /&gt;
      &lt;/font&gt;&lt;font color="blue"&gt;return &lt;/font&gt;&lt;font color="black"&gt;numerator / denominator&lt;/font&gt;&lt;font color="blue"&gt;;&lt;br /&gt;
    &lt;/font&gt;&lt;font color="black"&gt;}&lt;br /&gt;
}&lt;/font&gt;  &lt;/div&gt;
&lt;p&gt; The fit framework matches the column names with the object property names and executes the quotient method.  Pretty cool.  A .Net version of the framework can be downloaded from &lt;a href="http://fit.c2.com/wiki.cgi?DownloadNow"&gt;here&lt;/a&gt;. &lt;/p&gt;
&lt;img src="http://ridgway.co.za/aggbug/104.aspx" width="1" height="1" /&gt;</description>
            <guid>http://ridgway.co.za/archive/2005/07/16/acceptancetestingfit.aspx</guid>
            <pubDate>Sat, 16 Jul 2005 01:42:24 GMT</pubDate>
            <comments>http://ridgway.co.za/archive/2005/07/16/acceptancetestingfit.aspx#feedback</comments>
            <wfw:commentRss>http://ridgway.co.za/comments/commentRss/104.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>