Unit Testing Dynamic XAP Files

By now, you probably are aware that you can dynamically load XAP files using the Managed Extensibility Framework (MEF) within your Silverlight applications. Have you been scratching your head, however, and wondering how on earth you would actually test something like that?

It is possible, and here’s a quick post to show one way you can.

First, we need a decent deployment service. You’re not really going to hard-code the download and management, are you? I didn’t think so. If you need an example, look no further than the sample code I posted to Advanced Silverlight Applications using MEF. Here’s what the interface looks like:

public interface IDeploymentService
{
    void RequestXap(string xapName, Action<Exception> xapLoaded);       
       
    AggregateCatalog Catalog { get; }
}

This keeps it simple. Request the xap file, then specify a delegate for a callback. You’ll either get a null exception object (it was successful) or a non-null (uh… oh.)

Now, let’s focus on testing it using the Silverlight Unit Testing Framework. The first caveat is that you cannot use it on the file system. This means that your project will not work if you run it with a test page rather than hooking it to a web server (local or not).

Doing this is simple. In your ASP.NET project, go to the Silverlight tab and add your test project. When you are adding it, there is an option to generate a test page. I typically have one “test” web project with all of my test Silverlight applications, so I will have multiple test pages. To run a particular test, you simply set your ASP.NET web project as the start up project, then the corresponding test page (we’re talking the aspx, not the html) as the start page. I usually delete the automatically generated HTML pages.

Now we need to give MEF a test container. The caveat here is that, without a lot of work, it’s not straightforward to reconfigure the host container so you’ll want to make sure you test a given dynamic XAP file only once, because once it’s loaded, it’s loaded.

This is what my application object ends up looking like:

public partial class App
{
    public AggregateCatalog TestCatalog { get; private set; }

    public App()
    {
        Startup += Application_Startup;            
        InitializeComponent();
    }

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        // set up a catalog for tests
        TestCatalog = new AggregateCatalog();
        TestCatalog.Catalogs.Add(new DeploymentCatalog());

        var container = new CompositionContainer(TestCatalog);

        CompositionHost.Initialize(container);

        // now set up the unit testing framework
        var settings = UnitTestSystem.CreateDefaultSettings();
        RootVisual = UnitTestSystem.CreateTestPage(settings);
    }              
}

Here, I haven’t composed anything, just set up the container.

Now I’m going to add a simple dynamic XAP for testing. I add a new Silverlight application and wire it to the test web site but do NOT generate a test page. I blow away the App.xaml and MainPage.xaml resources, and add a simple class called Exports. Here is my class:

public class Exports
{
    private const string TESTTEXT = "TestText";

    [Export(TESTTEXT, typeof(string))]
    public string TestText { get { return TESTTEXT; } }
}

Yes, you got it – just a simple export of a string value. Now let’s write our test. I create a new test class and decorate it with the TestClass attribute. I am also running asynchronous tests, so it’s best to inherit the test from SilverlightTest which has some base methods for asynchronous testing.

Let’s take a look at the set up for my test:

[TestClass]
    public class DeploymentServiceTest : SilverlightTest
    {
        private const string DYNAMIC_XAP = "DynamicXap.xap";
        private const string TESTTEXT = "TestText";

        private DeploymentService _target;
    
        [Import(TESTTEXT, AllowDefault = true, AllowRecomposition = true)]
        public string TestString { get; set; }
     
        public DeploymentServiceTest()
        {
            CompositionInitializer.SatisfyImports(this);
        }

        [TestInitialize]
        public void TestInit()
        {
            if (Application.Current.Host.Source.Scheme.Contains("file"))
            {
                _target = null;
            }
            else
            {
                _target = new DeploymentService();
                ((App) Application.Current).TestCatalog.Catalogs.Add(_target.Catalog);
            }
        }
}

So right now I’m simply setting up my targets. The property is key – by composing imports on construction, I register my test class with the MEF system. Right now, however, I haven’t loaded anything, so it won’t be able to satisfy the import. By using AllowDefault true, however, I tell it I’m expecting something later and setting it to null is fine. The recomposition is what will trigger an update once the catalogs change. I also reach out to the test catalog I set up in the main application and add the catalog from my deployment service to it. Note that if I am running on the file system, I don’t bother setting up my service.

Next, I can add a stub to determine if I can even test this. If I am running from the file system, the deployment service is never set up. I created a helpful method that asserts an “inconclusive” when this is the case:

private bool _CheckWeb()
{
    if (_target == null)
    {
        Assert.Inconclusive("Cannot test deployment service from a test page. Must be hosted in web.");
        return false;
    }

    return true;
}        

Now we can write our main test. First, we check to make sure we are in a web context. Then, we load the xap, and once it is loaded, confirm there were no errors and that our property was successfully set:

[Asynchronous]
[TestMethod]
public void TestValidXap()
{
    if (!_CheckWeb())
    {
        return;
    }

    Assert.IsTrue(string.IsNullOrEmpty(TestString), "Test string should be null or empty at start of test.");
    _target.RequestXap(DYNAMIC_XAP, exception =>
                                        {
                                            Assert.IsNull(exception, "Test failed: exception returned.");
                                            Assert.IsFalse(string.IsNullOrEmpty(TestString),
                                                            "Test failed: string was not populated.");
                                            Assert.AreEqual(TESTTEXT, TestString,
                                                            "Test failed: property does not match.");
            }
}

And that’s pretty much all there is to it – of course, I am also adding checks for things like contract validation (are you passing me a valid xap name?) and managing duplicates, but you get the picture.

Jeremy Likness

Deploy Your Equipment Locally and Globally

For the better part of a decade, Atmosera has owned, operated, and offered TYPE-II SSAE 16 compliant data centers to clients who need secure space, power, and cooling to deploy their mission critical applications. We also leverage 21 additional data centers in the U.S. and abroad through strategic alliances. We offer a range of options from racks and full cabinets to secure cages. We also have network connectivity from several service providers.
Clients benefit from multiple hardened layers of security, reliability, and protection, combined with rigorous operational and maintenance procedures. We provide professional services that include remote hands, monitoring, and backup. We operate three data centers in the Portland Metropolitan area: Data Center 1 (DC1) and Data Center 2 (DC2) located in Beaverton, and Data Center 3 (DC3) located downtown Portland.

Physical Specifications

DC1 provides clients an ideal space to deploy their infrastructure and mission critical applications. We offer a safe and secure environment complete with space, power, and cooling with the following features:

  • Nearly 3,500 square foot
  • Flat stable ground with no known faults, flood plains or other geological threats and out of any flight paths
  • Choice of space in shared and private cabinets, in full-height and partial-cabinet increments
  • All full-height and new partial-size cabinets use a perforated door
  • Older partial-size private cabinets (1/2, 1/3 and 1/4) provide a solid door with fan
  • Cabinets are bolted to the foundation for seismic stability
  • Overhead anchored ladders provide additional vertical stability

Electrical Power Systems

In the unlikely event of failure, Atmosera’s power systems are designed to run uninterrupted. We have dedicated PGE (Portland General Electric) 1500kVA Clean Wind℠ electrical service into dual 300kVA CleanSource® UPS systems with efficient flywheel energy storage plus dual battery- powered 300kVA UPS systems. The UPS systems are configured 2N and are backed up by three independent diesel generators with a combined capacity of 1400kVA. The generators are exercised every month for 
60 minutes under load.

Primary and Secondary Electrical Power Systems

Power to the data center is provided by a 2N system. Primary power is provided by Portland General Electric (PGE) through a
dedicated 1500kVA 3-phase 277/480VAC transformer and power feed.

There are two secondary systems: A and B. Either the A or B system is capable of running the full load and half of the 
air conditioning systems. The A and B systems have independent transfer switches, Uninterruptible Power Supplies (UPSs) 
and power distribution. UPS and mechanical power loads have independent transfer switches.

Power Switching

Automatic Transfer Switches (ATSs) connect the primary and secondary power systems to the data center load. In the event of 
a power or phase loss, the ATSs detect the anomaly, start the generators and transfer the load. Generators are on-line, with load, within 10 seconds. Ten minutes after stable primary power is restored and stable, the ATSs transfer the load back to primary power.

Annunciator panels in the Command Center monitors ATS switching conditions. The ATSs are automatically tested under load every other week as part of the generator exercise schedule.

Service Transformers

Four Mirus Harmony-2TM harmonic mitigating transformers convert the 277/480VAC into 208/120VAC for use in the data center.

Power to the Cabinets

Full- and half-sized cabinets in Data Center 1 have dual power feeds. One-third and smaller cabinets have a single power feed. Default power configurations include:

  • Full cabinet, 30”, 34”, and 39” deep: 2x20 Amp. (power configurations available up to redundant three-phase 30 Amp, 208 V)
  • 1/2 cabinet, 30” deep: 1x20 Amp or 2x10 Amp. (Power configuration is cabinet- specific.)
  • 1/3 cabinet, 39” deep: 1x20 Amp or 2x20 Amp. and 30” deep: 1x10 Amp.
  • 1/4 cabinet, 30” deep and Super Condo, 30” or 39” deep: 1x7 Amp.
  • Condo. 30” deep: 1x4 Amp.

HVAC and Mechanical

Cooling is provided by Liebert 30 ton AC systems. A hot/cold aisle containment system saves energy and improves cooling efficiencies.

Fire Detection/Suppression Systems

Atmosera’s facilities are protected by twi independent zone-based fire detection systems connected to a remotely monitored alarm system.

Ionized particle, smoke detectors are located throughout the data center. Additionally a laser-based smoke detection system monitors the data center, colocation and UPS zone environments. Ambient air in each zone is continuously sampled by a VESDA laser-based smoke detection system to test for contaminants. Monitors for airborne particles, precursors to smoke detection is announced locally and to the local fire jurisdiction.

Detection of either an ionized or VESDA-triggered fire alarm is the first step in charging the pre-action, dry pipe, fire suppression system with water. A second high temperature event is required to fully charge the system — either a high temperature reading in the data center or colocation facility, a burst sprinkler head or an active fire alarm pull station. At this point, water would only be discharged from the sprinklers with ruptured temperature- sensitive discs.

Networking and Telecommunications

Atmosera is a carrier-neutral facility with multiple providers, including AboveNet, CenturyLink, Level 3, Comcast, Freewire Broadband, Frontier, Integra, LS Networks and Time Warner.

Atmosera is a founding member of the Northwest Access Exchange (NWAX), a regional Internet exchange with a Point of Presence (PoP) at Atmosera. NWAX provides peering and transit services over a gigabit Ethernet fabric, and interconnects nearly 20 major ISP, business and public/education networks, providing the highest possible performance with local peers.

Three Tier 1 providers — Level 3, AboveNet and CenturyLink — deliver upstream Internet bandwidth capacity on GigE fiber.

Data Cabling

Data cabling at Atmosera is switched gigabit and 100BaseT Ethernet network.

Physical Security

Atmosera personnel are on site at the facility 24x7x365. They monitor for intrusion detection with internal alarming and an external security service. Entrance is by card key and Bioscrypt™ fingerprint verification for colocation clients. Physical access is restricted to Atmosera employees for all other services. Multiple surveillance cameras monitor all activity, and all access is logged. Each client’s cabinet enclosure is secured with an individual lock and key. (There are no “community cabinets,” with the exception of our shared-space Colo Condo offerings.)

Data Security

Atmosera has laid down an extensive minefield to prevent unauthorized access to your information.

Atmosera’s infrastructure, applications and data are protected by high-end firewalls that are monitored in the company’s Command Center. The Command Center monitors all aspects of its Cloud hosting services and end-to-end network infrastructure 24/7/365, using SolarWinds® proven Orion network and application performance tools. Atmosera’s Monitoring and Standards Specialist is a SolarWinds Certified Professional (SCP).

Maintenance

Standard maintenance occurs Tuesdays from midnight to 6 a.m. Emergency maintenance occurs midnight to 6 a.m.

We deliver solutions that accelerate the value of Azure.

Ready to experience the full power of Microsoft Azure?

Start Today

Blog Home

Stay Connected

Upcoming Events

All Events