Testing Orchard drivers

If you’ve ever tried to test Orchard part drivers, you may have been blocked by the fact that the methods on drivers are protected. That, fortunately, doesn’t mean they are untestable. Those methods are still accessible through explicit interface implementations. In particular, drivers implement IContentPartDriver, which is defined as follows.

public interface IContentPartDriver : IDependency {
    DriverResult BuildDisplay(BuildDisplayContext context);
    DriverResult BuildEditor(BuildEditorContext context);
    DriverResult UpdateEditor(UpdateEditorContext context);
    void Importing(ImportContentContext context);
    void Imported(ImportContentContext context);
    void Exporting(ExportContentContext context);
    void Exported(ExportContentContext context);
    IEnumerable<ContentPartInfo> GetPartInfo();
    void GetContentItemMetadata(GetContentItemMetadataContext context);
}

By casting your driver to this interface, you get public access to these methods.

For example, here is some code I wrote recently to test the import and export methods of a driver:

[Test]
public void ImportGetAllDefinedProperties() {
    var doc = XElement.Parse(@"
<data>
<UspsShippingMethodPart
    Name=""Foo""
    Size=""L""
    WidthInInches=""10""
    LengthInInches=""11""
    HeightInInches=""12""
    MaximumWeightInOunces=""1.3""
    Priority=""14""
    International=""true""
    RegisteredMail=""true""
    Insurance=""false""
    ReturnReceipt=""true""
    CertificateOfMailing=""true""
    ElectronicConfirmation=""true""/>
</data>
");
    var driver = new UspsShippingMethodPartDriver(null)
        as IContentPartDriver;
    var part = new UspsShippingMethodPart();
    Helpers.PreparePart<UspsShippingMethodPart, UspsShippingMethodPartRecord>(
        part, "UspsShippingMethod");
    var context = new ImportContentContext(
        part.ContentItem, doc, new ImportContentSession(null));
    driver.Importing(context);

    Assert.That(part.Name, Is.EqualTo("Foo"));
    Assert.That(part.Size, Is.EqualTo("L"));
    Assert.That(part.WidthInInches, Is.EqualTo(10));
    Assert.That(part.LengthInInches, Is.EqualTo(11));
    Assert.That(part.HeightInInches, Is.EqualTo(12));
    Assert.That(part.MaximumWeightInOunces, Is.EqualTo(1.3));
    Assert.That(part.Priority, Is.EqualTo(14));
    Assert.That(part.International, Is.True);
    Assert.That(part.RegisteredMail, Is.True);
    Assert.That(part.Insurance, Is.False);
    Assert.That(part.ReturnReceipt, Is.True);
    Assert.That(part.CertificateOfMailing, Is.True);
    Assert.That(part.ElectronicConfirmation, Is.True);
}

[Test]
public void ExportSetsAllAttributes() {
    var driver = new UspsShippingMethodPartDriver(null)
        as IContentPartDriver;
    var part = new UspsShippingMethodPart();
    Helpers.PreparePart<UspsShippingMethodPart, UspsShippingMethodPartRecord>(
        part, "UspsShippingMethod");
    part.Name = "Foo";
    part.Size = "L";
    part.WidthInInches = 10;
    part.LengthInInches = 11;
    part.HeightInInches = 12;
    part.MaximumWeightInOunces = 1.3;
    part.Priority = 14;
    part.International = true;
    part.RegisteredMail = true;
    part.Insurance = false;
    part.ReturnReceipt = true;
    part.CertificateOfMailing = true;
    part.ElectronicConfirmation = true;

    var doc = new XElement("data");
    var context = new ExportContentContext(part.ContentItem, doc);
    driver.Exporting(context);
    var el = doc.Element("UspsShippingMethodPart");

    Assert.That(el, Is.Not.Null);
    Assert.That(el.Attr("Name"), Is.EqualTo("Foo"));
    Assert.That(el.Attr("Size"), Is.EqualTo("L"));
    Assert.That(el.Attr("WidthInInches"), Is.EqualTo("10"));
    Assert.That(el.Attr("LengthInInches"), Is.EqualTo("11"));
    Assert.That(el.Attr("HeightInInches"), Is.EqualTo("12"));
    Assert.That(el.Attr("MaximumWeightInOunces"), Is.EqualTo("1.3"));
    Assert.That(el.Attr("Priority"), Is.EqualTo("14"));
    Assert.That(el.Attr("International"), Is.EqualTo("true"));
    Assert.That(el.Attr("RegisteredMail"), Is.EqualTo("true"));
    Assert.That(el.Attr("Insurance"), Is.EqualTo("false"));
    Assert.That(el.Attr("ReturnReceipt"), Is.EqualTo("true"));
    Assert.That(el.Attr("CertificateOfMailing"), Is.EqualTo("true"));
    Assert.That(el.Attr("ElectronicConfirmation"), Is.EqualTo("true"));
}

The Attr method, in case you're wondering, is an extension method I blogged about yesterday.

The Helper class that I’m using here massages a fake part to behave like a real part. It gives the part a fake record, and adds a fake content item around it. It might not be enough in all situations, but it does make the fake convincing enough in this case.

public static ContentItem PreparePart<TPart, TRecord>(
    TPart part, string contentType, int id = -1)
    where TPart: ContentPart<TRecord>
    where TRecord: ContentPartRecord, new() {

    part.Record = new TRecord();
    var contentItem = part.ContentItem = new ContentItem
    {
        VersionRecord = new ContentItemVersionRecord
        {
            ContentItemRecord = new ContentItemRecord()
        },
        ContentType = contentType
    };
    contentItem.Record.Id = id;
    contentItem.Weld(part);
    return contentItem;
}

No Comments