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
JonReevesJonReeves 

Test Coverage Advise with CurrentPage & nonDraft Knowledge

Hey guys,

we've recently started implementing SF, and I'm helping out with the VF pages and Apex Classes. My background is mainly web development, but have struggled through the Apex Class parts of this process. During the trial I wrote a class that we were able to utilize, However since going live I've been introduced to the Sandbox and TestMethod steps.

 

I spent the best part of yesterday wrestling with my Class, trying to build some testMethods to cover the code. I understand the importance of this and want to do it properly however I've ran into a few issues that I was hoping I might get help on.

 

I should note that the class works absolutely fine, I'm just unable to edit it in any way until I can write a testMethod that works.

 

First some info... I've written an extension class for an Article Type (Knowledge) standard controller. It is currently implemented like so:

public class queryDocument{
     
    public queryDocument(ApexPages.StandardController stdController) {
    }

}

 This appeared to be the accepted way to get an extension written.

 

So my questions are as follows:

  1. How do I get access to the Record's Fields in the Class without using: "ApexPages.currentPage().getParameters().get('id');" and running a SOQL for each method.
  2. Or How can I write a testMethod (within this Class) to spoof the CurrentRecord / or Page... I think I've got this done, but wanted to check
    // Do an Insert
    List<Virtual_Support_Team__kav> testList = new List<Virtual_Support_Team__kav>{};
    Virtual_Support_Team__kav testItem = new Virtual_Support_Team__kav(Title = 'TestTitle', UrlName = 'TestTitle', Section_Code__c = 'TestCode', Product__c = 'TestProduct');
    testList.add(testItem);
    Insert testList;
    // Retrieve Insert
    List<Virtual_Support_Team__kav> insertedItem = [SELECT Title, Id, KnowledgeArticleId FROM Virtual_Support_Team__kav WHERE Id IN :testList];
    
    // Set ID
    PageReference testPage = new PageReference('/apex/VirtualSupportTeam?id='+insertedItem[0].KnowledgeArticleId ); 
    Test.setCurrentPage(testPage);
  3. Lastly my main problem/question... The KnowledgeArticleVersion table (which is what is the model used when requesting custom object Virtual_Support_Team__kav), requires that your SELECT includes a PublishStatus and Language condition (WHERE). The problem is, any INSERT done via the API by default gets the PublishStatus = Draft, and you cannot set this to Online, which is the condition I SELECT based on in my code. How can I ever get the testMethod to cover these portions of code? An example of my code is below:
    /**[ Video Content from Guide Article ]********************/
    public List<ContentVersion> getVideoContentFromGuide() {
    	// Get Article ID
    	String articleId = ApexPages.currentPage().getParameters().get('id');
    	
    	// Get current Article Details
    	List<Virtual_Support_Team__kav> art = new List<Virtual_Support_Team__kav>();
    	art = [SELECT Section_Code__c, Product__c FROM Virtual_Support_Team__kav WHERE KnowledgeArticleId = :articleId AND PublishStatus = 'Online' AND Language = 'en_US'];
    
    	// Prepare Related List Object
    	List<ContentVersion> videos = new List<ContentVersion>();
    			
    	//Handle no Article
    	if (art.size() != 0){
    		// Build Search Term
    		String searchTerm = art[0].Product__c + '%Training Video%[%' + art[0].Section_Code__c + '%]%';
    		
    		// Look for Video Content
    		videos = [SELECT Id, ContentDocument.title, ContentDocument.LatestPublishedVersionId, ContentUrl, FileType FROM ContentVersion WHERE ContentDocument.Title LIKE :searchTerm AND PublishStatus = 'P' AND isLatest = true LIMIT 1];
    	}
    	
    	// List of Video from Content Library
    	return videos;      
    }

Any advice would be greatly appreciated. As I'm at a bit of a loss.

cheers,

Jon

JonReevesJonReeves

I'd since discovered this Post, which seems to outline a good solution (for my main issue [3]):

http://boards.developerforce.com/t5/Apex-Code-Development/How-to-create-a-knowledgebase-kav-with-PublishStatus-Online-for/td-p/197110

 

However I'm not entirely sure how to implement the parameter parsing as it was my understanding that from VF pages you cannot pass parameters to the Class via the Repeat Element? I'm guessing by allowing the parameter to be optional and setting the default to Online, it will cover both senarios.. however I'm not sure of the syntax for that.

 

Any suggestions?

 

cheers,

Jon

Prady01Prady01

Hello there... If you using extensions in VF page.... then this might be helpful when writting test class for extensions..

object obj = new object();
        obj.RecordTypeId = [SELECT Id FROM RecordType where Name = '-------' and sObjectType = '-----' and IsActive = true LIMIT 1].Id;
        obj.Name = 'FSA' + oIHO.Name;
        obj.FSA_Status__c = 'Submitted';
        obj.Implementation_Hand_Off__c = oIHO.Id;
        insert obj;
		ApexPages.StandardController standardcontroller = new ApexPages.StandardController(obj);

 And if you working with contentversion object the test class should be something like this.... Hope it helps :)... Sorry if it didnt...

RecordType ContentRT = [select Id FROM RecordType WHERE SobjectType =:'ContentVersion'and id=:'012400000009Bj8AAE']; //Name=:'Sales Documents'];
        ContentVersion testContentInsert =new ContentVersion(); 
        testContentInsert.ContentURL='http://www.google.com/'; 
        testContentInsert.Title ='Google.com'; 
        testContentInsert.RecordTypeId = ContentRT.Id; 
        insert testContentInsert; 
        ContentVersion testContent = [SELECT ContentDocumentId,Opportunity__c,DreamTeam_Project__c FROM ContentVersion where Id = :testContentInsert.Id]; 
        ContentWorkspace testWorkspace = [SELECT Id FROM ContentWorkspace WHERE Name=:'Opportunity Documents']; 
        ContentWorkspaceDoc newWorkspaceDoc =new ContentWorkspaceDoc(); 
        newWorkspaceDoc.ContentWorkspaceId = testWorkspace.Id; 
        newWorkspaceDoc.ContentDocumentId = testContent.ContentDocumentId; 
        insert newWorkspaceDoc;
        testContent.Opportunity__c =op.id; 
        update testContent;

 

JonReevesJonReeves

Hi Pradeep,

cheers for your input. I've looked at what you've said, but couldn't follow how it would overcome the PublishStatus issue I ran into. Perhaps I'm not understanding it fully.

 

I did however find a workarround that has allowed me to get CodeCoverage (essentially 100%, because it skips over the workaround/overloadingbit). It was using a term I'd not heard before called Overloading. Information found here:

http://success.salesforce.com/ideaview?id=087300000007qoZAAQ

 

Basically I had to allow the Status parameter to be passed, but then set a default value by means of Overloading the method. Allowing me to use it in a VF page without Parameter, or via TestMethod by forcing a parameter.

 

My Code block looks like this now:

/**[ Video Content from Guide Article ]********************/
public List<ContentVersion> getVideoContentFromGuide(String status) {
	String articleId = ApexPages.currentPage().getParameters().get('id');
	
	// Get current Article Details
	List<Virtual_Support_Team__kav> art = new List<Virtual_Support_Team__kav>();
	art = Database.query('SELECT Id, KnowledgeArticleId, Section_Code__c, Product__c, Type__c FROM Virtual_Support_Team__kav WHERE KnowledgeArticleId = \'' + articleId + '\' AND PublishStatus = \''+status+'\' AND Language = \'en_US\'');

	List<ContentVersion> videos = new List<ContentVersion>();
			
	//Handle no Article
	if (art.size() != 0){
		// Build Search Term
		String searchTerm = art[0].Product__c + '%Training Video%[%' + art[0].Section_Code__c + '%]%';
		
		// Look for Video Content
		videos = [SELECT Id, ContentDocument.title, ContentDocument.LatestPublishedVersionId, ContentUrl, FileType FROM ContentVersion WHERE ContentDocument.Title LIKE :searchTerm AND PublishStatus = 'P' AND isLatest = true LIMIT 1];
	}
	
	// List of Videos
	return videos;      
}
public List<ContentVersion> getVideoContentFromGuide() {
	return this.getVideoContentFromGuide('Online');
}

 

And my Test Method like this:

/**[ Test Method ]********************/
static testMethod void myTest1() {
	Test.StartTest();
	
	// Construct
	ApexPages.StandardController controller = new ApexPages.StandardController(new Task());
	knowledgeLearningCenterArticleHandler extension = new knowledgeLearningCenterArticleHandler(controller);
	
	// Insert Dummy
	List<Virtual_Support_Team__kav> testList = new List<Virtual_Support_Team__kav>{};
	Virtual_Support_Team__kav testItem = new Virtual_Support_Team__kav(Keywords__c = 'Test,Testing', Language = 'en_US', Title = 'TestTitle', UrlName = 'TestTitle', Section_Code__c = 'TestCode', Product__c = 'TestProduct', Type__c = 'Guide');
	testList.add(testItem);
	Insert testList;
	List<Virtual_Support_Team__kav> insertedItem = [SELECT Title, Id, KnowledgeArticleId FROM Virtual_Support_Team__kav WHERE Id IN :testList];
	
	// Set ID
	PageReference testPage = new PageReference('/apex/VirtualSupportTeam?id='+insertedItem[0].KnowledgeArticleId ); 
	Test.setCurrentPage(testPage);

	// Run Code (and pass parameter for test)
	extension.getVideoContentFromGuide('Draft');
	
	Test.StopTest();
}

 

At least I'm now able to Deploy my class again. Can someone comment as to this is a good solution, or not?

 

 

Also any thoughts on my first question?

 

I think I'd seen someone write into the Constructor class something like:

this.record = ApexPages.currentPage().getRecord();

 

and then being able to access that all in the methods, as this.record? It'd be nice to eliminate the SOQL at the begining of each method to get the Record that the page is refering to.

 

cheers,

Jon