function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
adreameradreamer 

Test methods and namespaces

Hi All,

 

Do the test methods have to be written after a namespace has been defined ? If yes, then the test code is specific to the namespace and if I want to reuse the code in a new namespace I need to change all the references to the old one.

 

Let me give you an example of what I mean.

 

Say I am looking at the test code for a Visualforce/Controller. In the test method I need to set the page reference for the test and I need to create an instance of the controller. In both cases I need to prepend the namespace to the page and controller. For example, if my namespace is "abc" then this would lead to:

 

Test.setCurrentPage(Page.abc__MyPage);

 

abc__MyController cont = new abc__MyController();

 

So if I want to reuse the source code, including the test code in with a new namespace -i.e. in a new and different org, I need to change all the references to the namespace in the test code.

 

Is this the case ?

 

Thanks,

Fernando

Best Answer chosen by Admin (Salesforce Developers) 
aalbertaalbert

If that code is included within a managed apex class, you don't need to reference the namespace. Its implicitly defaulted as stated here: http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_classes_namespace_prefix.htm?SearchType=Stem

 

Below is a simple apex test I ran without my managed package. Notice how one dynamic soql string includes the namespace, the other doesnt. Both return identical results. 

 

List<test__c> tests = [Select a.aaNamespace__AutoNumber__c, a.Name, a.IsDeleted, (Select Name From aaNamespace__tests2__r) From aaNamespace__test__c a];
   	 String soqlwithnamespace = 'Select a.aaNamespace__AutoNumber__c, a.Name, a.IsDeleted, (Select Name From aaNamespace__tests2__r) From aaNamespace__test__c a';
   	 List<sObject> l = Database.query(soqlwithnamespace);
   	 
   	 String soqlwithoutnamespaces = 'Select a.AutoNumber__c, a.Name, a.IsDeleted, (Select Name From tests2__r) From test__c a';
   	 List<sObject> x = Database.query(soqlwithoutnamespaces);

Have you tried to remove the namespace references in your soql query? That will allow your code to be reused throughout different development environments , which may be testing with other namespaces. 

 

All Answers

aalbertaalbert

No, I do not believe you need prepend or reference the namespace in the test methods. That is internally resolved once its included in the managed package and the tests execute upon install. But as the developer, you shouldn't need to hardcode the namespace like that. 

adreameradreamer

Hi Aalbert,

 

Thank you for your reply.

 

Yes, you are of course right.

 

The issue I had was different than what I thought and I will describe it here as it may help other developers and you may want to add your input too.

 

In this particular application we use dynamic soql so string queries are created on the fly at runtime depending on user input on the UI. When generating these queries we use the schema to get the query fields at runtime too so there there is no problem with the namespace because the describe results will include the namespace prefixed to the fields. However there are some instances where we need to add extra fields to string "by hand". For example, when the query field involves a relationship such as MyCustomObject__r.Name. So the test methods were failing at that once a namespace was defined for the org.

 

For me the lesson is that when one has to hardcode a query field in a query string to execute dynamic soql, and if a namespace is used in the org, then the namespace prefix has to be added to these manually added query fields.

 

We do the development in development orgs, including testing code, and then migrate everything to another org for packaging where we define the namespace. The idea is that the development org has the generic code that later can be packaged.

 

If you think we can improve in this process please let us know.

 

Thank you again !

Fernando

aalbertaalbert

So you are doing describe() calls in apex to generate the SOQL string dynamically, correct? And you are manually concatenating the namespace when reference child relationships? Can you post a snippet? The describe call should include the namespace even for child relationships. I wonder if we can find a way to avoid your namespace concatenation. 

 

 

adreameradreamer

Thank you for help.

 

Here is snippet of the code:

 

String expQueryFields = Utils.calculateExpenditureQueryFields();
String expenditureQuery = 'Select '+ expQueryFields + ', apd2__Department__r.Name From apd2__Expenditure__c WHERE apd2__Period__c >= '+dtFromStr+' AND apd2__Period__c <= '+dtToStr;
ID aggregateBatchJob = Database.executeBatch(new ExpenditureAggregationBatch(expenditureQuery,this.aggregateByValue,this.batch.Aggregate_From_Date__c,this.batch.Aggregate_To_Date__c,url));


There is also an additional angle to it that I didn't mention to keep things as simple as possible in my post. There are queries that involve sub queries. For instance in a query to the Account object we also inlude a subquery to fetch all the Contacts for each account record. Then when looping over the response, we need to get the childs for each record -e.g. the contacts for each account, so there we have the same probelm. For instance:

 

                          SObject[] queryResultObjs = stdSetCont.getRecords(); // stdSetCont is a standard set controller
                   
                            for(SObject queryResultObj:queryResultObjs)
                            {
                                String supplierName = (String)queryResultObj.get('apd2__Supplier_Name__c');
                                String invNbr = (String)queryResultObj.get('apd2__Invoice_Number__c');
                                if(supplierToInvNbrMap.containsKey(supplierName))
                                {
                                    List<String> invNbrs = supplierToInvNbrMap.get(supplierName);
                                    invNbrs.add(invNbr);
                                }
                                else
                                {
                                    List<String> invNbrs = new List<String>();
                                    invNbrs.add(invNbr);
                                    supplierToInvNbrMap.put(supplierName,invNbrs);
                                }
                            }


Thanks again for your input.

 

Regards,

Fernando

aalbertaalbert

If that code is included within a managed apex class, you don't need to reference the namespace. Its implicitly defaulted as stated here: http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_classes_namespace_prefix.htm?SearchType=Stem

 

Below is a simple apex test I ran without my managed package. Notice how one dynamic soql string includes the namespace, the other doesnt. Both return identical results. 

 

List<test__c> tests = [Select a.aaNamespace__AutoNumber__c, a.Name, a.IsDeleted, (Select Name From aaNamespace__tests2__r) From aaNamespace__test__c a];
   	 String soqlwithnamespace = 'Select a.aaNamespace__AutoNumber__c, a.Name, a.IsDeleted, (Select Name From aaNamespace__tests2__r) From aaNamespace__test__c a';
   	 List<sObject> l = Database.query(soqlwithnamespace);
   	 
   	 String soqlwithoutnamespaces = 'Select a.AutoNumber__c, a.Name, a.IsDeleted, (Select Name From tests2__r) From test__c a';
   	 List<sObject> x = Database.query(soqlwithoutnamespaces);

Have you tried to remove the namespace references in your soql query? That will allow your code to be reused throughout different development environments , which may be testing with other namespaces. 

 

This was selected as the best answer
adreameradreamer

Thanks Albert !