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
Vishal (Sops)Vishal (Sops) 

Can you guys help me to write a test class

This is my code to simpy update a field on custom object from the task. I have never written a test class so please help me out to compose it.

 

trigger SandboxCC on Task (before update,after update) {

if(Trigger.isUpdate){

for(Task t : Trigger.new)
{

if(t.IsClosed == True && t.subject.contains('App Preview Sent to Customer'))
{
for(CC_Card__c c : [Select c.Id, c.stage__c From CC_Card__c c ])
{
c.stage__c = 'Preview & Iterate';
c.a_Preview_Date__c = system.today();
update c;
}

}

}
}
}

Best Answer chosen by Admin (Salesforce Developers) 
AdrianCCAdrianCC

Dude, your code is better now but still not fully bulkified... For example, if the trigger fires on more than one task record(more tasks, like in the case of a dataloader operation) you are still doing the select for Cards and the update cardslist for each task. You need to move that for outside of the if:

trigger CCCards on Task (after update) {

	//Preparting CCCards to Update
	public list<CC_Card__c> CardsToUpdate = new List<CC_Card__c>();
	public set<Id> CCCardIDs = new Set<Id>();


	if(Trigger.isUpdate){

		for(Task t : Trigger.new)
		{

			if(t.IsClosed == True && t.subject.contains('App Preview Sent to Customer'))
			{
				CCCardIDs.add(t.WhatId);
			}  

			for(CC_Card__c c : [Select c.Id, c.stage__c From CC_Card__c c where Id in :CCCardIDs])
			{
				c.stage__c = 'Preview & Iterate';
				c.a_Preview_Date__c = system.today();
				CardsToUpdate.add(c);
			}
			update CardsToUpdate; 
		}
	}
}

Also remove one of the time conditions on the trigger, leave just one, either before or after, no need for both...

 

 

And yes, the test class. I forgotten about that, sorry :P

@isTest
private TestCCCards {

	static testMethod void myUnitTest() {
		//create a new Card
		CC_Card__c card = new CC_Card__c(Name='test');//put here the required fields
		insert card;

		//create a new Task
		Task task = new Task(WhatId=card.Id, Name='test task', IsClosed=false, Subject='test subject');
		insert task;

		Test.startTest();
		//we simulate the trigger conditions
		task.IsClosed = true;
		task.subject = 'App Preview Sent to Customer';
		update task;
		Test.stopTest();

		//the trigger has fired and we check that the card fields have been modified
		List<CC_Card__c> cardList = [SELECT Id, stage__c, a_Preview_Date__c FROM CC_Card__c WHERE Id=:card.Id];
		System.assertEquals('Preview & Iterate', cardList[0].stage__c);
		System.assertEquals(Date.today(), cardList[0].a_Preview_Date__c);

	}
}

 You run it (from eclipse) right clicking on the file in the package explorer > Force.com > Run Tests.

 

 

Thanks,

Adi

 

All Answers

vishal@forcevishal@force

Why are you calling it on before as well as after?

 

I don't see any difference in the logic. So you are actually executing this twice without any need.

 

Secondly, you are querying inside a FOR loop. So your trigger isn't bulkified.

 

On every update of Task, do you have to update all the CC_Card__c records in the database? Any relation between Task and CC_Card__c?

Vishal (Sops)Vishal (Sops)

yes you are right. For every task, whole database is getting updated, how can I correct that? thanks a lot for your help

AdrianCCAdrianCC

Read the comments and adapt the code to your situation. Check this:

trigger SandboxCC on Task (before update) {
	Set<String> idsSet = new Set<String>();
	for(Task t : Trigger.new) {
		if(t.IsClosed == True && t.subject.contains('App Preview Sent to Customer')) {
			//we add the id of the task to a Set
			idsSet.add(t.Id);
		}
	}

	//we check that we have ids that match the criteria
	if (idsSet.size() > 0) {
		//we extract the related CC_Card__c list
		//I've presumed that the relationship is called Task__c and is a Lookup(Task)
		List<CC_Card__c> cardList = [SELECT Id FROM CC_Card__c WHERE Task__c IN :idsSet];
		if ((cardList != null) && (cardList.size() > 0)) {
			for (CC_Card__c c : cardList) {
				c.stage__c = 'Preview & Iterate';
				c.a_Preview_Date__c = system.today();
			}
			try {
				update cardList;
			} catch (Exception ex) {
				System.debug('Error updating the cardList: ' + ex.getMessage());
			}
		}
	}
}

 

 

Tkxs,

Adrian

Vishal (Sops)Vishal (Sops)

Thanks Man, I was also working for similar sort of code, here is my bit.

 

trigger CCCards on Task (before update,after update) {

//Preparting CCCards to Update
public list<CC_Card__c> CardsToUpdate = new List<CC_Card__c>();
public set<Id> CCCardIDs = new Set<Id>();


if(Trigger.isUpdate){

for(Task t : Trigger.new)
{

if(t.IsClosed == True && t.subject.contains('App Preview Sent to Customer'))
{

CCCardIDs.add(t.WhatId);
for(CC_Card__c c : [Select c.Id, c.stage__c From CC_Card__c c where Id in :CCCardIDs])
{
c.stage__c = 'Preview & Iterate';
c.a_Preview_Date__c = system.today();
CardsToUpdate.add(c);
}
update CardsToUpdate;
}   

}

}

 

 

But I am struggling to write a test class, can you help me in that..thanks a ton.

AdrianCCAdrianCC

Dude, your code is better now but still not fully bulkified... For example, if the trigger fires on more than one task record(more tasks, like in the case of a dataloader operation) you are still doing the select for Cards and the update cardslist for each task. You need to move that for outside of the if:

trigger CCCards on Task (after update) {

	//Preparting CCCards to Update
	public list<CC_Card__c> CardsToUpdate = new List<CC_Card__c>();
	public set<Id> CCCardIDs = new Set<Id>();


	if(Trigger.isUpdate){

		for(Task t : Trigger.new)
		{

			if(t.IsClosed == True && t.subject.contains('App Preview Sent to Customer'))
			{
				CCCardIDs.add(t.WhatId);
			}  

			for(CC_Card__c c : [Select c.Id, c.stage__c From CC_Card__c c where Id in :CCCardIDs])
			{
				c.stage__c = 'Preview & Iterate';
				c.a_Preview_Date__c = system.today();
				CardsToUpdate.add(c);
			}
			update CardsToUpdate; 
		}
	}
}

Also remove one of the time conditions on the trigger, leave just one, either before or after, no need for both...

 

 

And yes, the test class. I forgotten about that, sorry :P

@isTest
private TestCCCards {

	static testMethod void myUnitTest() {
		//create a new Card
		CC_Card__c card = new CC_Card__c(Name='test');//put here the required fields
		insert card;

		//create a new Task
		Task task = new Task(WhatId=card.Id, Name='test task', IsClosed=false, Subject='test subject');
		insert task;

		Test.startTest();
		//we simulate the trigger conditions
		task.IsClosed = true;
		task.subject = 'App Preview Sent to Customer';
		update task;
		Test.stopTest();

		//the trigger has fired and we check that the card fields have been modified
		List<CC_Card__c> cardList = [SELECT Id, stage__c, a_Preview_Date__c FROM CC_Card__c WHERE Id=:card.Id];
		System.assertEquals('Preview & Iterate', cardList[0].stage__c);
		System.assertEquals(Date.today(), cardList[0].a_Preview_Date__c);

	}
}

 You run it (from eclipse) right clicking on the file in the package explorer > Force.com > Run Tests.

 

 

Thanks,

Adi

 

This was selected as the best answer
Vishal (Sops)Vishal (Sops)

Thanks boss, just a question. I have a required field at CC Card object and that is primary contact. This is a lookup field to contacts. How do I incorporate this in test class. I mean what should I add in here.

 

CC_Card__c card = new CC_Card__c(Name='test', Primary_Contact__c=??)

 

 

vishal@forcevishal@force

For this, create a test contact record in your test method.

 

Contact c = new Contact (LastName = 'test'); // add any other fields, if required.

insert c;

 

CC_Card__c card = new CC_Card__c(Name='test', Primary_Contact__c=c.Id);

 

 

This should do the job for you!

Vishal (Sops)Vishal (Sops)

that is awesome, I have a question just for my knowledge, here I had only one task "App Preview Sent to Customer". But what if there are multiple tasks and I need to update stage's status according to that? How would I make that bulkified.