Quantcast
Channel: Andy in the Cloud
Viewing all articles
Browse latest Browse all 119

Summer’13 Pre-Release : Metadata API, Tooling API and Apex Mocking?

$
0
0

I’m so excited to start this blog post I don’t know where to begin!?! Before I do however, please keep in mind that this is based on pre-release information and environments made available by Salesforce and as such maybe subject to change. As you probably have gathered by now, I’m very keen on API’s and my two favourite API’s have had a good level of improvements. There is also of course Apex improvements, more so in the testing area this time, also a favourite!

Metadata API – Installing Packages and Cancelling Deployments

This API has steadily tracked new component types over the past releases, as you’d expect. However for this release we get some significantly new functionality. Those keen on automation and build systems will love! That is the ability to programatically install and uninstall packages!

All you need is the namespace and the version of your package, thats it! Its design piggy backs from the current deploy and create operations as a new InstalledPackage Metadata component. Meaning you can either handle it as a file based deployment (from Ant for example) or my favourite via the create operation programatically, which I’ll be sure to be trying via the Apex Metadata API once this moves to Sandbox.

If you go file based, the approach is to create a .installedPackage file and place it in the /installedPackages subfolder, the filename is your namespace, e.g. mynamespace.installedPackage

<InstalledPackage xmlns="http://soap.sforce.com/2006/04/metadata">
    <versionNumber>1.0</versionNumber>
    <password>optional_password</password>
</InstalledPackage>

Then reference it in the package.xml as you would any other component before making a deploy call, either programatically or via Salesforce Migration Toolkit using Ant.

<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>mynamespace</members>
        <name>InstalledPackage</name>
    </types>
    <version>28.0</version>
</Package>

To uninstall a package, you guessed it, define this component in the destructivePackage.xml file as you would any other component. Finally, you can now cancel those long running deployments if you realise you’ve made a mistake and don’t want to continue to lock your org before you can correct it! There does not appear to be an API for this, but you can find it under the Monitor Deployments page. The pre-release Metadata API doc for Summer’13 is here.

Tooling API – Better Symbol Tables!

After writing my initial blog on this API I found myself a little wanting, in terms of more granular SymbolTable and the process for which it was produced. The release notes say this “In version 28.0, Tooling API includes expanded functionality to retrieve symbol tables, raw logs, and checkpoints, and create custom fields.“. I managed to find the pre-release document for the Tooling API here. I’ll be watching this closely.

A quick peak at the Tooling API WSDL shows that the granularity has been improved we now have a innerClasses member for the SymbolTable. And rather exciting is the SymbolTable is now part of the ApexClass type, does this mean its now generally available without the need to compile? I’ll let you know soon!

<xsd:complexType name="ApexClass">
    <xsd:complexContent>
        <xsd:extension base="tns:sObject">
            <xsd:sequence>
                <xsd:element name="ApiVersion" minOccurs="0" type="xsd:double" nillable="true"/>
                <xsd:element name="Body" minOccurs="0" type="xsd:string" nillable="true"/>
                <xsd:element name="BodyCrc" minOccurs="0" type="xsd:double" nillable="true"/>
                <xsd:element name="CreatedBy" minOccurs="0" type="tns:User" nillable="true"/>
                <xsd:element name="CreatedById" minOccurs="0" type="tns:ID" nillable="true"/>
                <xsd:element name="CreatedDate" minOccurs="0" type="xsd:dateTime" nillable="true"/>
                <xsd:element name="IsValid" minOccurs="0" type="xsd:boolean" nillable="true"/>
                <xsd:element name="LastModifiedBy" minOccurs="0" type="tns:User" nillable="true"/>
                <xsd:element name="LastModifiedById" minOccurs="0" type="tns:ID" nillable="true"/>
                <xsd:element name="LastModifiedDate" minOccurs="0" type="xsd:dateTime" nillable="true"/>
                <xsd:element name="LengthWithoutComments" minOccurs="0" type="xsd:int" nillable="true"/>
                <xsd:element name="Name" minOccurs="0" type="xsd:string" nillable="true"/>
                <xsd:element name="NamespacePrefix" minOccurs="0" type="xsd:string" nillable="true"/>
                <xsd:element name="Status" minOccurs="0" type="xsd:string" nillable="true"/>
                <xsd:element name="SymbolTable" minOccurs="0" type="tns:SymbolTable" nillable="true"/>
                <xsd:element name="SystemModstamp" minOccurs="0" type="xsd:dateTime" nillable="true"/>
        </xsd:sequence>
    </xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="SymbolTable">
    <xsd:sequence>
        <xsd:element name="constructors" minOccurs="0" maxOccurs="unbounded" type="tns:Constructor"/>
        <xsd:element name="externalReferences" minOccurs="0" maxOccurs="unbounded" type="tns:ExternalReference"/>
        <xsd:element name="id" type="xsd:string"/>
        <xsd:element name="innerClasses" minOccurs="0" maxOccurs="unbounded" type="tns:SymbolTable"/>
        <xsd:element name="methods" minOccurs="0" maxOccurs="unbounded" type="tns:Method"/>
        <xsd:element name="name" type="xsd:string"/>
        <xsd:element name="namespace" type="xsd:string"/>
        <xsd:element name="properties" minOccurs="0" maxOccurs="unbounded" type="tns:VisibilitySymbol"/>
        <xsd:element name="tableDeclaration" type="tns:Symbol"/>
        <xsd:element name="variables" minOccurs="0" maxOccurs="unbounded" type="tns:Symbol"/>
    </xsd:sequence>
</xsd:complexType>

Apex Testing Improvements, Apex Mocking?

If you’ve read Josh Kaplan’s excellent blog about Apex Test Code Segregation you’ll not be surprised by the news in the release notes that all your test code must now reside in a separate class. However what you might then ask is, “Does this not make accessing the state of my classes harder as I have to make more things public?”.

Fear not the new @TestVisible annotation can help. This new annotation is mostly related to the afore mentioned enforced placement of test code in test classes when adopting API version 28.0. The Salesforce release notes have this to say in respect to this feature and the new requirement…

‘This annotation can also be handy when you upgrade the Salesforce.com API version of existing classes containing mixed test
and non-test code. Because test methods aren’t allowed in non-test classes starting in API version 28.0, you must move the
test methods from the old class into a new test class (a class annotated with isTest) when you upgrade the API version of
your class. You might run into visibility issues when accessing private methods or member variables of the original class. In
this case, just annotate these private members with TestVisible.’

The following trigger and class example shows the feature in action, providing a means to test just the calculation logic, without exposing the method or the state it needs to other consumers of the class. Of course you may well find testing only your public methods more desirable from an encapsulation and best practice perspective. Either way, the following should give you and idea of what can be achieved with the new annotation.

/**
 * Trigger ensures new work order lines are added (update tbd) validations and recalcs occur
 **/
trigger WorkOrderLinesItemTrigger on WorkOrderLineItem__c (before insert) {

	Set workOrderIds = new Set();
	for(WorkOrderLineItem__c workOrderLine : Trigger.new)
		workOrderIds.add(workOrderLine.WorkOrder__c);

	WorkOrders workOrders = new WorkOrders(workOrderIds);
	workOrders.addLines(Trigger.new);
	workOrders.updateWorkOrders();
}

/**
 * Class helps add lines to Work Orders recalculating the costs and combining lines etc
 **/
public with sharing class WorkOrders
{
	@TestVisible private List<WorkOrder__c> m_workOrders;

	@TestVisible private Map<WorkOrder__c, List<WorkOrderLineItem__c>> m_workOrderLines;

	@TestVisible
	private WorkOrders() { }

	/**
	 * Loads existing work orders and lines
	 **/
	public WorkOrders(Set workOrderIds)
	{
		m_workOrders = null; // TODO: Load existing Work Orders
		m_workOrderLines = null; // TODO: Load existing Work Order Lines
	}

	public void addLines(Map<Id, List<WorkOrderLineItem__c>> workOrderLines)
	{
		// TODO: Add new lines into map
		// ...

		// TODO: Perform other processing on the lines, validations, adjustments etc...
		// ...

		// Recalcualte the Work Order cost
		recalculateCost();
	}

	public void updateWorkOrders()
	{
		update m_workOrders;
	}

	@TestVisible
	private void recalculateCost()
	{
		// Recalculate the cost on each Work Order via m_workOrderLines
		for(WorkOrder__c workOrder : m_workOrderLines.keySet())
		{
			Decimal workOrderCost = 0;
			List<WorkOrderLineItem__c> workOrderLines = m_workOrderLines.get(workOrder);
			for(WorkOrderLineItem__c workOrderLine : workOrderLines)
			{
				// Total hours, cost, discounts etc...
				// ...
			}
			workOrder.Cost__c = workOrderCost;
		}
	}
}

@IsTest
private with sharing class WorkOrdersTest {

	static testmethod void testRecalculateCost()
	{
		// Test data to call recalculateCost method
		WorkOrders workOrders = new WorkOrders();
		workOrders.m_workOrderLines =
			new Map<WorkOrder__c, List<WorkOrderLineItem__c>>
				{ new WorkOrder__c () =>
					new List<WorkOrderLineItem__c> {
							new WorkOrderLineItem__c () } };

		// Unit test the recalculateCost method
		workOrders.recalculateCost();

		// Assert data
		for(WorkOrder__c workOrder : workOrders.m_workOrderLines.keySet())
			System.assertEquals(0, workOrder.Cost__c);
	}
}}

@TestVisible Usage and Best Practice

So is this an approach to help with mocking in Apex? Possibly, perhaps to safely expose your own mocking solutions and interfaces in your code? You do need to consider how much more tightly coupled your tests become to your code and the maintenance of that when using this feature. You may simply find sticking to testing your public methods a better approach and only using this feature as a means to ease initial migration to API 28.0.

Those following my Apex Enterprise Patterns series may recognise the broad functional encapsulation pattern I’m using above. I’ve have some thoughts on how to apply this new feature to more cleanly expose some of the mocking features I’ve added to those patterns recently, which I will consider once the feature is more out in the wild.

Finally, a fellow MVP, Matt Lacey, has also recently written an excellent blog bost on Apex Tests best practices check it out here. You can also read in general about Summer’13 here and here from another MVP, Daniel Hoechst.

Other Summmer’13 Pre-Release Blog Posts

There has been a few others blogs relating to other Summer’13 Pre-Release details.



Viewing all articles
Browse latest Browse all 119

Trending Articles