trying to write a test for an apex trigger - triggers

I'm working on a trigger/test class and i can't figure out how to get the test class to work. I know that i need to update my opportunity to use the trigger but i'm not sure how to and then how to verify that my trigger is working.
Trigger:
trigger add_primary_advisor on Opportunity(before update) {
for(Opportunity o: Trigger.new){
if (o.IsClosed && !Trigger.oldMap.get(o.id).IsClosed) {
OpportunityContactRole contactRole =
[select ContactID from OpportunityContactRole where IsPrimary = true and OpportunityId = :o.id];
if (contactRole != null) {
o.Primary_Advisor__c=contactRole.ContactID;
}
}
}
}
Test class:
#isTest
private class primary_advisor_test {
static testMethod void primary_advisor(){
Opportunity opp = new Opportunity(Name='test opp', StageName='stage', Probability = 95, CloseDate=system.today());
insert opp;
update opp;
}
}

Before going into the solution for the test class I would like to point out the trigger is not builkified as you have a SOQL query inside you for loop which is not a best practice.
I am not aware of the exact functionality of the opportunityContactRole object, I am just assuming that it is a object which will hold the contact id and the opportunityID, more or less like a junction object.
#isTest
private class primary_advisor_test {
static testMethod void primary_advisor(){
//Create a contact that will be added to the opportunityCOntactRole.
contact con = new contact(name='testCon');// add all the required field as per your org settings
insert Con;
Opportunity opp = new Opportunity(Name='test opp', StageName='stage', Probability = 95, CloseDate=system.today());
insert opp;
//Create the opporunityContactRole.
opportunityCOntactRole oppCOn = new new opportunityCOntactRole(OpportunityId=opp.id, contactId= con.Id, isPrimary=true);
insert oppCon;
//update the opportunity so that it is closed and enters the if conditon in your trigger.
opp.stageName='Closed';
update opp;
}
}

The problem is you didn't changed any fields before calling update try this
opp.Probability = 90;
update opp;

Related

Manage invoke from listeners / create history object before transaction end

I have a function which update a customer.
Furthermore, I have a function which creates an Activity (createActivity)
Now I want to add to the Activity Entity also the reference to my Custom Audit Table (AuditRevision). Therefore, I try to get the last object from the History Entity (= Function: findLastRevisionFromEntity).
The problem is, that I got the object before from the Custom Audit Table because it seems that the creation from the CustomAudit entry is invoked at the whole end from updateCustomer. So, I will e.g. save AuditRevision with ID = 5, but for the current operation it's ID=6.
Any idea how I can fix this?
I'm also fine if I call the listener from Envers manually instead of automatically, but how can I do this? How can I invoke the function (public void newRevision(Object revisionEntity)) from the RevisionListener?
public void updateCustomer(Customer customer){
entityManager.merge(customer);
// Create Activity
activitiesProcessServiceBean.createActivity(customer,
customer.getEmployeeCreatorOrUpdate(),
Activities.ActionType.MODIFY.toString());
}
public Activities createActivity(EntityPropertyFinder entityPropertyFinder, Employee employeeCreator,
String activityType){
LOGGER.info("START createActivity");
Activities newActivities = new Activities();
// AuditRevision
AuditRevision auditRevision = jpaAuditUtilBean.findLastRevisionFromEntity(entityPropertyFinder.getClass(),
entityPropertyFinder.getId());
newActivities.setAuditRevision(auditRevision);
activitiesService.addActivities(newActivities);
return newActivities;
}
public AuditRevision findLastRevisionFromEntity(Class<? extends EntityPropertyFinder> class1, Long entityId) {
AuditReader auditReader = AuditReaderFactory.get(entityManager);
Object[] lastRevision = (Object[]) auditReader.createQuery()
.forRevisionsOfEntity(class1, false, false)
.add(AuditEntity.property("id").eq(entityId))
.addOrder(AuditEntity.revisionNumber().desc())
.setMaxResults(1)
.getSingleResult();
if(lastRevision == null)
return null;
AuditRevision auditRevision = (AuditRevision) lastRevision[1];
return auditRevision;
}

Trigger to run only after checkbox goes rom unchecked to checked

I want to run a trigger on Contact if a checkbox on Contact object goes from unchecked state to checked state and then do some processing on the records. I have this trigger on after insert and after update. The code works fine for update but if I check the box while creating a new contact record, the trigger does not detect the below condition in the code and therefore sends an empty list to contactTriggerHandler class.
if (Trigger.oldMap.get(con.Id).checkbox==false && con.checkbox== true)
trigger Contact on Contact (after update, after insert) {
List<Contact> listofContacts = new List<Contact>();
List<Contact> usersToCreate= new List<Contact>();
if (Trigger.isAfter) {
if(trigger.isInsert){
System.debug('After insert');
if(RecursiveTriggerHandler.isFirstTime){
RecursiveTriggerHandler.isFirstTime = false;
for (Contact con : Trigger.new) {
Contact contacttoUpdate = con.clone(true,true);
contacttoupdate.Nickname__c=contacttoUpdate.firstname;
listofContacts.add(contacttoUpdate);
}
System.debug(listofContacts);
ContactTriggerHandler.AfterInsert(listofContacts);
update listofContacts;
}
}
else if(trigger.isUpdate){
System.debug('After insert and update function');
if(RecursiveTriggerHandler.isFirstTime){
RecursiveTriggerHandler.isFirstTime = false;
for (Contact con : Trigger.new) {
Contact contacttoUpdate = con.clone(true,true);
contacttoupdate.Nickname__c=contacttoUpdate.firstname;
listofContacts.add(contacttoUpdate);
if (Trigger.oldMap.get(con.Id).checkbox==false && con.checkbox== true) {
usersToCreate.add(contacttoUpdate);
}
}
ContactTriggerHandler.AfterInsert(usersToCreate);
update listofContacts;
}
}
}
}
Here is the recursive handler class:
public class RecursiveTriggerHandler{
public static Boolean isFirstTime = true;
}

Test class for Apex Trigger

I am new in Apex Development.
I want to write a TestClass for my Apex Trigger.
I am sharing my code with you.
trigger UpdateContact on Account (after Insert) {
List <Contact> contactList=new List<Contact>();
for(Account a:Trigger.new)
{
Contact c=new Contact(LastName=a.Name, AccountId=a.id);
contactList.add(c);
}
insert contactList;
}
Since your trigger in on Account (after insert), provided that there is no other mandatory field or validation rule, just simply insert an account to test your trigger:
#isTest
private class UpdateContactTest
{
static testMethod void myUnitTest()
{
Account acc = new Account(
Name = 'Test');
insert acc;
}
}

Failure Message: "System.QueryException: No such column 'Address' on entity 'Lead'. I

I am passing all test coverage in salesforce apex in sandbox but in deploying to live getting the
error in subject, i dont know how to handle it.
my test class code is:
#isTest(SeeAllData=true)
public class myLeadTest{
public static testMethod void testMyController5() {
Account acc= new Account(name='test');
acc.Order__c='wee';
insert acc;
Campaign camp = new Campaign(Name='test');
insert camp;
Company__c cm= new Company__c();
cm.Company_Id__c=12;
cm.Name='234';
cm.Account__c=acc.id;
insert cm;
Lead l= new Lead();
l.Campaign__c=camp.Id;
l.LastName='test';
l.Company='cmpny';
l.Company_Id__c=cm.Company_Id__c;
l.Email='test#yahoo.com';
l.Status='Closed - Converted';
l.Order__c=acc.Order__c;
// l.Auto_Convert__c=true;
// l.IsConverted=false;
//l.ConvertedAccountId=acc.Id;
Lead[] l2= new Lead[]{l};
insert l2;
Opportunity op= new Opportunity ();
op.StageName='Won (Agency)';
op.Name='test';
op.CloseDate=Date.valueOf('2015-04-28');
op.AccountId=acc.id;
op.LeadSource='web';
op.StageName= 'Won (Agency)';
op.CampaignId=camp.id;
op.TrialStart__c=Date.valueOf('2012-04-28');
insert op;
Contact cnt= new Contact();
cnt.LastName='test';
cnt.AccountId=acc.id;
cnt.ASEO_Company_Id__c=12;
cnt.Email=l.Email;
cnt.Company__c=cm.id;
insert cnt;
///////////////
/* Lead l5= new Lead();
l5.Campaign__c=camp.Id;
l5.LastName='test';
l5.Company='cmpny';
l5.Company_Id__c=12;
l5.Email='test#yahoo.com';
l5.Status='Closed-Converted';
l5.isConverted=false;
//l.ConvertedAccountId=acc.Id;
insert l5; */
Contact cnt1= new Contact();
cnt1.LastName='test';
cnt1.AccountId=acc.id;
cnt1.ASEO_Company_Id__c=12;
cnt1.Email=l.Email;
insert cnt1;
Database.LeadConvert leadConvert = new Database.LeadConvert();
leadConvert.setLeadId(l2[0].Id);
LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
leadConvert.setConvertedStatus(convertStatus.MasterLabel);
leadConvert.setOpportunityName(op.Name);
leadConvert.setConvertedStatus('Closed - Converted');
Database.LeadConvertResult lcResult = Database.ConvertLead(leadConvert);
// MyLead.addCampaign(l2[0], camp.Name);
// MyLead.updateOpportunity(l2[0], lcResult);
// MyLead.updateContact( l2[0], lcResult, cm) ;
// myLead.addCampaignMembers(l2);
}
}
and class code which i call in trigger :
public class MyLead {
public static void convertLead(Lead[] leads) {
Database.LeadConvert leadConvert = new Database.LeadConvert();
for (Lead lead :leads) {
if (!(lead.IsConverted)) {
// Check if an account exists with email. Attach Contact and Account, convert Lead.
Contact[] myContacts = [SELECT Id, AccountId FROM Contact WHERE Email = :lead.Email Limit 1];
if (myContacts.size() == 1) {
System.debug('Existing Contact');
MyLead.attachExistingConvert(lead, myContacts[0]);
}
else {
System.debug('No existing contact');
if (lead.Auto_Convert__c) {
MyLead.addCampaign(lead, lead.Campaign__c);
leadConvert.setLeadId(lead.Id);
leadConvert.setConvertedStatus('Closed - Converted');
Database.LeadConvertResult lcResult = Database.ConvertLead(leadConvert);
// Populate the newly created records with extra data.
MyLead.updateOpportunity(lead, lcResult);
Company__c myCompany = [SELECT Id FROM Company__c WHERE Company_Id__c = :lead.Company_Id__c];
MyLead.updateContact(lead, lcResult, myCompany);
// Must update the Company before Account otherwise the Account lookup will fail.
MyLead.updateCompany(lead, lcResult, myCompany);
MyLead.updateAccount(lead, lcResult, myCompany);
}
}
}
}
}
// Attaches Lead to Contact and Account if matched by Email, converts Lead and creates opportunity if it doesn't exist.
public static void attachExistingConvert(Lead lead, Contact contact) {
MyLead.addCampaign(lead, lead.Campaign__c);
Database.leadConvert leadConvert = new Database.LeadConvert();
leadConvert.setLeadId(lead.Id);
leadConvert.setConvertedStatus('Closed - Converted');
leadConvert.setContactId(contact.Id);
leadConvert.setAccountId(contact.AccountId);
leadConvert.setSendNotificationEmail(True);
// Do not create an opportunity if any exist.
Opportunity[] myOpportunity = [SELECT Id FROM Opportunity WHERE AccountId = :contact.AccountId];
if (myOpportunity.size() > 0) {
leadConvert.setDoNotCreateOpportunity(True);
}
leadConvert.setLeadId(lead.Id);
Database.LeadConvertResult leadConvertResult = Database.convertLead(leadConvert);
// If we created an opportunity, update it with extra stuff.
if (leadConvert.isDoNotCreateOpportunity() == False) {
MyLead.updateOpportunity(lead, leadConvertResult);
}
}
// Updates the newly created Opportunity with extra data
public static void updateOpportunity(Lead lead, Database.LeadConvertResult lcResult) {
Opportunity myOpportunity = [SELECT Id, StageName FROM Opportunity WHERE Id = :lcResult.opportunityId];
myOpportunity.Name = 'Online Upgrade';
myOpportunity.TrialStart__c = lead.CreatedDate.date();
//myOpportunity.Amount = lead.Monthly_Revenue__c;
myOpportunity.Amount = lead.Amount__c;
myOpportunity.Type = 'New Business';
myOpportunity.LeadSource = 'Website';
myOpportunity.Order__c = lead.Order__c;
DateTime dt = System.now();
Date d = dt.date();
myOpportunity.CloseDate = d;
myOpportunity.StageName = lead.Agency__c ? 'Won (Agency)' : 'Won (End User)';
myOpportunity.Probability = 100;
update myOpportunity;
}
// Updates the newly created Account with extra data
public static void updateAccount(Lead lead, Database.LeadConvertResult lcResult, Company__c myCompany) {
Account myAccount = [SELECT Id FROM Account WHERE Id = :lcResult.accountId];
myAccount.Type = 'Customer';
myAccount.ASEO_Company_Id__c = lead.Company_Id__c;
myAccount.Company__c = myCompany.Id; // Setting the company will cause the company account lookup to fail
myAccount.Order__c = lead.Order__c;
update myAccount;
}
// Updates the newly created Contact with extra data
public static void updateContact(Lead lead, Database.LeadConvertResult lcResult, Company__c myCompany) {
Contact myContact = [SELECT Id FROM Contact WHERE Id = :lcResult.contactId];
myContact.ASEO_Company_Id__c = lead.Company_Id__c;
myContact.Company__c = myCompany.Id;
update myContact;
}
// Updates the Company with extra data
public static void updateCompany(Lead lead, Database.LeadConvertResult lcResult, Company__c myCompany) {
myCompany.Account__c = lcResult.accountId;
update myCompany;
}
// Adds a lead to a campaign
public static void addCampaign(Lead lead, String campaign) {
Campaign[] myCampaigns = [Select Id FROM Campaign WHERE Name = :campaign LIMIT 1];
if (myCampaigns.size() == 1) {
CampaignMember campaignMember = new CampaignMember (campaignId=myCampaigns[0].Id, leadId=lead.Id);
insert campaignMember;
}
}
// Create campaign members from leads. Campaign comes from lead.Campaign__c.
public static void addCampaignMembers(Lead[] leads) {
for (Lead lead :leads) {
// Might want to query Campaigns table instead.
//Set<String> campaigns = new Set<String>();
//campaigns.add('Freemium');
Campaign[] myCampaigns = [SELECT Id FROM Campaign WHERE Name = :lead.Campaign__c LIMIT 1];
//if (campaigns.contains(lead.Campaign__c)) {
if (myCampaigns.size() == 1) {
MyLead.addCampaign(lead, lead.Campaign__c);
}
}
}
}
and my lead trigger is:
trigger LeadTrigger on Lead (after insert, after update) {
Lead[] leads = Trigger.new;
//MyLead.createOpportunity(leads);
MyLead.convertLead(leads);
Please any one can help me, i tries 25 times but in deploying to production give me error in the given subject, or any one give code coverage of this class, thank you in advance
Looks like the issue is based on a soql query that is not included in your code. You try to query a field called "Address" but this field doesn't exist. Address is still in beta...
Try to adjust your query and use the fields City, Street, Country and PostalCode.
You can learn more about sObject fields there: http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_lead.htm
Just in case someone else get to this question with this problem.
As Christian said, the code is trying to access the "Address" field from Lead in a SOQL query. Starting from API version 30, the compound fields are available to use in queries (http://www.salesforce.com/us/developer/docs/api/Content/compound_fields_address.htm).
So, if you run into this issue with a query in your code, check for the API version of the class and the visualforce page. Both must be 30 or greater.

Try to have unique OpportunityLineItem APEX-CODE

I'm currently working on a trigger for the OpportunityLineItem, every product on Salesforce are our "basic" products.
When a salesman will add a product to an opportunity he will also need to put the mpn ( = unique ID for a product) who will call our website to get the real price, because the real price depend of every option set on the product .
My trigger is calling a class to make the request, so far it's working!
But when i want to add the same couple of productID and mpn it will not work.
Problem:
The salesman will add a product OpportunityLineItem , but this product is already in his current OpportunityLineItem of his Opportunity so it will not work.
First, my trigger will not get the price because my SOQL request will return more than one result .
Here my trigger:
trigger GetRealPrice on OpportunityLineItem (after insert) {
for(OpportunityLineItem op : Trigger.new){
RequestTest.getThePrice(op.Id_UAD__c,op.MPN__c,op.OpportunityId);
}
}
Here the called class;
public class RequestTest {
//Future annotation to mark the method as async.
#Future(callout=true)
public static void getThePrice(Decimal idUad, String mpnProduct,String opID){
// Build the http request
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('http://www.site.com/mpn.getprice?id='+idUad+'&mpn='+mpnProduct);
req.setMethod('GET');
String result;
HttpResponse res = http.send(req);
System.debug(res.getBody());
result = res.getBody();
Decimal price = Decimal.valueof(result);
System.debug(opID);
OpportunityLineItem op = [SELECT UnitPrice FROM OpportunityLineItem
WHERE Id_UAD__c = :idUad
AND OpportunityId = :opID
AND MPN__c = :mpnProduct] ;
System.debug('you went through step1');
op.UnitPrice = price;
System.debug('This is the opportunity price'+op.UnitPrice);
update op;
}
}
Since you are looping through each line item in the trigger, pass the line item ID. Then change your method to handle the update per line item:
trigger GetRealPrice on OpportunityLineItem (after insert) {
for(OpportunityLineItem op : Trigger.new){
RequestTest.getThePrice(op.Id_UAD__c,op.MPN__c,op.Id);
}
}
...
public class RequestTest {
//Future annotation to mark the method as async.
#Future(callout=true)
public static void getThePrice(Decimal idUad, String mpnProduct,String opLineID){
...
Decimal price = Decimal.valueof(result);
System.debug(opID);
OpportunityLineItem op = [SELECT UnitPrice FROM OpportunityLineItem
WHERE Id = :opLineID] ;
op.UnitPrice = price;
System.debug('This is the opportunity price'+op.UnitPrice);
update op;
}
}