Hi i have a custom controller which clones opportunity with a new currency,clones quote and all its quote line item.A button on Quote page layout does all this.While writing a test class to cover this code,i could not cover certain lines and do not know why.The code is as follows :
CloneOppNewCurrencyController.cls :
public with sharing class CloneOppNewCurrencyController {
public List<DatedConversionRate>lstCurrencies{get;set;}
public String selectedCurrency{get;set;}
public List<SelectOption> cTypes{get;set;}
public boolean flag{get;set;}
public Date closeDate;
public String qId{get;set;}
public Quote qObj{get;set;}
public Quote qClone{get;set;}
public Opportunity oppObj;
public Opportunity oppClone{get;set;}
public List<QuoteLineItem> lstQuoteLineItems;
public List<QuoteLineItem> lstClonedQuoteLineItems;
public QuoteLineItem clonedQuoteLineItem;
public Double exchangeRate;
public Map<String,Double>mapExchangeRates;
public List<PriceBookEntry> pbe;
public List<Id>pb;
public Quote testClone{get;set;}
public Map<Id,PricebookEntry>mapProIdNpBookEntry;
public List<Renewed_Entitlement__c> lstRE;
public List<Quoted_Asset__c> lstQuotedAsset;
public Renewed_Entitlement__c cloneRE;
public Quoted_Asset__c cloneQA;
//Constructor
public CloneOppNewCurrencyController() {
pb = new List<Id>();
lstRE = new List<Renewed_Entitlement__c>();
lstQuotedAsset = new List<Quoted_Asset__c>();
lstclonedQuoteLineItems = new List<QuoteLineItem>();
mapProIdNpBookEntry = new Map<Id,PriceBookEntry>();
//get quote Id from Page
qId=Apexpages.currentPage().getParameters().get('id');
//Get the Opp Id
qObj=[Select q.Total_Price__c, q.Total_Margin__c, q.Total_Cost__c, q.TotalPrice, q.Tax, q.SystemModstamp, q.Subtotal,
q.Status, q.Siebel_Id__c, q.ShippingStreet, q.ShippingState, q.ShippingPostalCode, q.ShippingName, q.ShippingHandling,
q.ShippingCountry, q.ShippingCity, q.Revision_Number__c, q.Quote_Expiry__c, q.Quote_Date__c, q.QuoteToStreet,
q.QuoteToState, q.QuoteToPostalCode, q.QuoteToName, q.QuoteToCountry, q.QuoteToCity, q.QuoteNumber, q.Pricebook2Id,
q.Price_Book__c, q.Phone, q.Opportunity.Id, q.OpportunityId, q.Name, q.LineItemCount, q.LastModifiedDate,
q.LastModifiedById, q.IsSyncing, q.IsDeleted, q.Internal_Notes__c, q.Id, q.GrandTotal, q.Fax, q.Email, q.Discount,
q.Description, q.Default_Payment_Terms__c, q.Customer_Comments__c, q.CurrencyIsoCode, q.CreatedDate, q.CreatedById,
q.ContactId, q.BillingStreet, q.BillingState, q.BillingPostalCode, q.BillingName, q.BillingCountry, q.BillingCity, q.Opportunity.CloseDate,
q.AdditionalStreet, q.AdditionalState, q.AdditionalPostalCode, q.AdditionalName, q.AdditionalCountry, q.AdditionalCity,
q.Account_Number__c, q.Account_Manager__c, q.Account_Manager_Phone__c, q.Account_Manager_Fax__c, q.Account_Manager_Email__c ,
q.Pricebook2.Organisation__c, q.Pricebook2.External_Id__c, q.Pricebook2.IsStandard, q.Pricebook2.Description, q.Pricebook2.IsActive,
q.Pricebook2.CurrencyIsoCode, q.Pricebook2.Name
From Quote q
where q.Id =:qId];
closeDate = qObj.Opportunity.CloseDate;
cTypes=new List<SelectOption>();
mapExchangeRates = new Map<String,Double>();
cTypes.add(new SelectOption('None','None'));
for(DatedConversionRate d:[Select StartDate, NextStartDate, IsoCode, Id, ConversionRate From DatedConversionRate where StartDate<=:closeDate and NextStartDate >=:closeDate]){
cTypes.add(new SelectOption(d.IsoCode,d.IsoCode));
mapExchangeRates.put(d.IsoCode,d.ConversionRate);
}
//query all fields in Opp which has this quote to clone it
oppObj = [Select o.X18_Character_Id__c, o.Win_Loss_Reason_Details__c, o.Win_Loss_Cancelled_Reason__c, o.Where_is_A_End__c,
o.Upload_Date_Time__c, o.Type, o.Total_Price__c, o.Total_Margin_in_Account_Currency__c, o.Total_Margin__c,
o.Total_Cost__c, o.Timescale__c, o.Technology_Margin__c, o.SystemModstamp, o.SyncedQuoteId, o.Suspended__c,
o.Start_of_Close_Date_FY__c, o.Start_of_Close_Date_FY_2__c, o.Start_of_Close_Date_FY_1__c, o.StageName,
o.Solution_Type__c, o.Solution_Description__c, o.Signed_SOW_Received__c, o.Siebel_Id__c, o.Service_Start_Date__c,
o.SecureCall_Margin__c, o.Salesforce_Opportunity_Id__c, o.Risk_Level__c, o.Regional_Contact_for_SFOne__c,
o.RecordTypeId, o.RFSDate__c, o.Probability, o.Primary_Competitor__c, o.Pricebook2Id, o.PS_Margin__c,
o.PO_Number__c, o.Owner_Affiliates__c, o.OwnerId, o.Other_Margin__c, o.Organisation__c,
o.OpenAir_Project_Reference__c, o.Number_of_Line_items__c, o.Non_Portfolio__c, o.NextStep, o.Need__c,
o.Name, o.NTT_Service_Family_Name__c, o.Maintenance_Margin__c, o.MSS_Margin__c, o.Lost_to__c, o.LeadSource,
o.Last_Update_Date_of_Phase__c, o.LastModifiedDate, o.LastModifiedById, o.LastActivityDate, o.Large_Deal__c,
o.IsWon, o.IsDeleted, o.IsClosed, o.Id, o.HasOpportunityLineItem, o.Group_Collaborator_s_Name__c,
o.ForecastCategoryName, o.ForecastCategory, o.FiscalYear, o.FiscalQuarter, o.Fiscal, o.ExpectedRevenue,
o.End_Customer__c, o.Description, o.CurrencyIsoCode, o.CreatedDate, o.CreatedById, o.Contract_Term__c,
o.Collaborate_with__c, o.Closed_Won_Status__c, o.Close_Date_this_FY__c, o.Close_Date_Last_FY__c, o.Pricebook2.CurrencyIsoCode,
o.CloseDate, o.CampaignId, o.Budget__c, o.Authority__c, o.Approval_Status__c, o.Amount, o.Account_Owner_Id__c, o.Pricebook2.IsActive,
o.Pricebook2.Organisation__c, o.Pricebook2.External_Id__c, o.Pricebook2.IsStandard, o.Pricebook2.Description, o.Pricebook2.Name ,
o.Account_Currency__c, o.AccountId, o.A_End_or_B_End_or_C_End__c
From Opportunity o
where o.Id =: qObj.OpportunityId];
lstQuoteLineItems = [Select q.Vendor_Cost_Name__c, q.UnitPrice, q.Total_Price__c, q.Total_Exchanged_Cost__c, q.Takeover_PPP__c, q.SystemModstamp,
q.Subtotal_Price__c, q.Subtotal, q.SortOrder, q.Single_Creation__c, q.Siebel_Id__c, q.Service_Start_Date__c,
q.Service_End_Date__c, q.Service_Calendar_Business_Hours__c, q.ServiceDate, q.Requested_Ship_Date__c, q.Renewed_Entitlement__c,
q.Renewal_Product__c, q.QuoteId, q.Quantity, q.PricebookEntryId, q.Price__c, q.Organisation__c, q.ListPrice, q.Line_No__c,
q.LineNumber, q.LastModifiedDate, q.LastModifiedById, q.IsDeleted, q.Install_Post_Code__c, q.Install_County_State__c,
q.Install_Country__c, q.Install_Contact__c, q.Install_City__c, q.Id, q.Exchanged_Cost__c, q.Exchange_Rate__c,
q.Discount__c, q.Discount, q.Description, q.Customer_Note__c, q.CurrencyIsoCode, q.CreatedDate, q.CreatedById,
q.Covered_Product__c, q.Covered_Asset__c, q.Cost__c, q.Cost_Price_Original__c, q.Cost_Exchange_Date__c,
q.Cost_Currency__c, q.Consolidated_Entitlement__c, q.Comments__c, q.Asset_Expires__c, q.Address_2__c, q.Vendor_RRP__c,
q.PricebookEntry.IsDeleted, q.PricebookEntry.ProductCode, q.PricebookEntry.SystemModstamp, q.PricebookEntry.LastModifiedById,
q.PricebookEntry.LastModifiedDate, q.PricebookEntry.CreatedById, q.PricebookEntry.CreatedDate, q.PricebookEntry.UseStandardPrice,
q.PricebookEntry.IsActive, q.PricebookEntry.UnitPrice, q.PricebookEntry.CurrencyIsoCode, q.PricebookEntry.Product2Id,
q.PricebookEntry.Pricebook2Id, q.PricebookEntry.Name, q.PricebookEntry.Id,
q.Address_1__c From QuoteLineItem q
where q.QuoteId =:qObj.Id];
for(QuoteLineItem oLineItem : lstQuoteLineItems) {
pb.add(oLineItem.PricebookEntry.Product2Id);
}
//query renewal entitlements under the query to clone it
lstRE = [Select r.Quote__c, r.Quote_Status__c, r.Quote_Line_Item__c, r.Opportunity__c, r.Name, r.Id, r.Entitlement__c,
r.Entitlement_Start_Date__c, r.Entitlement_Service_Calendar__c, r.Entitlement_Part_Code__c, r.Entitlement_End_Date__c,
r.CurrencyIsoCode
From Renewed_Entitlement__c r
where r.Quote__c =:qId ];
//query quoted assets under the query to clone it
lstQuotedAsset = [Select q.Quote__c, q.Name, q.Id, q.CurrencyIsoCode, q.Asset__c
From Quoted_Asset__c q
where q.Quote__c =:qId];
}
public void proceed() {
try {
if(selectedCurrency == 'None' || selectedCurrency == '') {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Please select a currency in order to proceed'));
}
pbe = [Select p.UnitPrice, p.Product2Id, p.Pricebook2Id, p.Name, p.IsActive, p.Id, p.CurrencyIsoCode From PricebookEntry p
where p.CurrencyIsoCode =:selectedCurrency and p.Pricebook2Id =:oppObj.Pricebook2Id and p.Product2Id in :pb];
for(PricebookEntry pbe : pbe) {
mapProIdNpBookEntry.put(pbe.Product2Id,pbe);
}
for(QuoteLineItem oLine:lstQuoteLineItems) {
if(!mapProIdNpBookEntry.containsKey(oLine.PricebookEntry.Product2Id)) {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'No pricebook entry exists for this particular currency.Hence kindly create an entry with the selected currency before cloning Opportunity.'));
return;
}
}
if(selectedCurrency!='None') {
if(oppObj.StageName!='Qualification') {
oppClone = oppObj.clone(false,true);
oppClone.ForecastCategoryName = 'Omitted';
oppClone.CurrencyIsoCode = selectedCurrency;
System.debug('Pricebook2Id::::' +oppClone.Pricebook2Id);
oppClone.Pricebook2Id = oppObj.Pricebook2Id;
oppClone.Name = selectedCurrency + oppObj.Name;
Database.insert(oppClone);
System.debug('Inserted Opp Currency >>> ' + oppClone.CurrencyIsoCode);
if(qObj.IsSyncing != true) {
qClone = qObj.clone();
qClone.Name = selectedCurrency + qObj.Name;
qClone.OpportunityId = oppClone.Id;
Database.insert(qClone);
System.debug('Inserted Quote Currency >>> ' + qClone.CurrencyIsoCode);
testClone= [SELECT Id, CurrencyIsoCode FROM Quote WHERE ID=:qClone.Id];
oppClone.SyncedQuoteId = qClone.Id;
}
else {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Synced Quote cannot be cloned.Please stop sync before cloning'));
}
Database.update(oppClone);
System.debug('Inserted Quote Currency >>> ' + testClone.CurrencyIsoCode);
}
if((lstRE!=null || !(lstRE.isEmpty())) && qClone.Id !=null) {
for(Renewed_Entitlement__c re:lstRE) {
cloneRE = new Renewed_Entitlement__c();
cloneRE = re.clone();
cloneRE.Quote__c = qClone.Id;
Database.insert(cloneRE);
}
}
if((lstQuotedAsset!=null || !(lstQuotedAsset.isEmpty())) && qClone.Id !=null) {
for(Quoted_Asset__c qa:lstQuotedAsset) {
cloneQA = new Quoted_Asset__c();
cloneQA = qa.clone();
cloneQA.Quote__c = qClone.Id;
Database.insert(cloneQA);
}
}
System.debug('^^^aaa^^^^^^^^'+mapProIdNpBookEntry);
if(qClone!=null) {
if(lstQuoteLineItems!=null) { System.debug('not null line items');//tbd
for(QuoteLineItem oLine:lstQuoteLineItems) {
clonedQuoteLineItem = new QuoteLineItem();
clonedQuoteLineItem = oLine.clone();
system.debug('^^12111111' + oLine.PricebookEntry.Product2Id);
if(mapProIdNpBookEntry.containsKey(oLine.PricebookEntry.Product2Id)) {
clonedQuoteLineItem.PricebookEntryId=mapProIdNpBookEntry.get(oLine.PricebookEntry.Product2Id).Id;
}
clonedQuoteLineItem.QuoteId = qClone.Id;
System.debug('Quote line Iso Code'+clonedQuoteLineItem.CurrencyIsoCode);
//update price,margin and vendors
if(mapExchangeRates.containsKey(selectedCurrency)) { System.debug('$$$containsKey iruku$$$'+'###value is###'+mapExchangeRates.get(selectedCurrency));
if(oLine.Price__c!=null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.Price__c = oLine.Price__c / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
if(oLine.UnitPrice != null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.UnitPrice = oLine.UnitPrice / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
if(oLine.Vendor_RRP__c != null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.Vendor_RRP__c = oLine.Vendor_RRP__c / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
}
lstclonedQuoteLineItems.add(clonedQuoteLineItem);
}
System.debug(' >>> ' + lstclonedQuoteLineItems);
if(lstclonedQuoteLineItems.size()>0) {
insert lstclonedQuoteLineItems;
}
}
}
}
}catch(Exception e) {
}
}
public pageReference cancel() {
return null;
}
}
testCloneNewCurrencyController.cls
#isTest(SeeALLData=true)
private class testCloneNewCurrencyController {
static testMethod void myUnitTest() {
// TO DO: implement unit test
Account account=new Account(Name='Test');
insert account;
Contact cn=new Contact(Accountid=account.id);
cn.LastName='test';
insert cn;
// set up opportunity name and price book id
String opportunityName = 'My Opportunity';
String standardPriceBookId = '';
PriceBook2 pb2Standard = [select Id from Pricebook2 where isStandard=true];
standardPriceBookId = pb2Standard.Id;
// set up opp and Verify that the results are as expected.
Opportunity o = new Opportunity(AccountId=account.Id, Name=opportunityName,
StageName='Prospecting', CloseDate=Date.today(),Contract_Term__c = 6);
insert o;
Opportunity opp = [SELECT Name FROM Opportunity WHERE Id = :o.Id];
System.assertEquals(opportunityName, opp.Name);
// set up product2 and Verify that the results are as expected.
Product2 p2 = new Product2(Name='Test Product',isActive=true,Product_Code_Upload__c = 'Test Product 1' , ProductCode = 'Test Product 1');
insert p2;
Product2 p2ex = [SELECT Name FROM Product2 WHERE Id = :p2.Id];
System.assertEquals('Test Product', p2ex.Name);
// set up PricebookEntry and Verify that the results are as expected.
PricebookEntry pbe = new PricebookEntry(Pricebook2Id=standardPriceBookId, Product2Id=p2.Id, UnitPrice=99, isActive=true );
insert pbe;
PricebookEntry pbeex = [SELECT Pricebook2Id FROM PricebookEntry WHERE Id = :pbe.Id];
System.assertEquals(standardPriceBookId, pbeex.Pricebook2Id);
// set up OpportunityLineItem and Verify that the results are as expected.
OpportunityLineItem oli = new OpportunityLineItem(PriceBookEntryId=pbe.Id, OpportunityId=o.Id, Quantity=1, UnitPrice=99 , Cost_Currency__c = 'USD',Cost__c=2000);
insert oli;
OpportunityLineItem oliex = [SELECT PriceBookEntryId FROM OpportunityLineItem WHERE Id = :oli.Id];
oli.Cost_Currency__C = 'GBP';
update oli;
update account;
Quote quot1 = new Quote(Name='Quote1',OpportunityId=o.Id,Pricebook2Id=standardPriceBookId);
insert quot1;
// set up OpportunityLineItem and Verify that the results are as expected.
QuoteLineItem qli = new QuoteLineItem(QuoteId = quot1.Id,PriceBookEntryId=pbe.Id,UnitPrice=1000, Quantity=1, Price__c=3500 , Cost_Currency__c = 'USD',Cost__c=2000);
insert qli;
// Create two Asset records and relate them to the oli through Ordered Asset records
Asset ass1 = new Asset(Name='Asset1',SerialNumber='12345',AccountId=account.Id,ContactId=cn.Id);
insert ass1;
Asset ass2 = new Asset(Name='Asset1',SerialNumber='678910',AccountId=account.Id,ContactId=cn.Id);
insert ass2;
Quoted_Asset__c ordass1 = new Quoted_Asset__c(Asset__c=ass1.Id,Quote_Line_Item__c=qli.Id,Quote__c=quot1.Id);
insert ordass1;
Quoted_Asset__c ordass2 = new Quoted_Asset__c(Asset__c=ass2.Id,Quote_Line_Item__c=qli.Id,Quote__c=quot1.Id);
insert ordass2;
// Check that the Serial numbers field on the QLI is as expected
QuoteLineItem quot1test = [SELECT LineNumber, Serial_Numbers__c FROM QuoteLineItem WHERE Id =: qli.Id];
Test.startTest();
Test.setCurrentPage(new Pagereference('/apex/CloneOppNewCurrency?id='+quot1.Id));
CloneOppNewCurrencyController c = new CloneOppNewCurrencyController();
c.selectedCurrency = 'USD';
system.assertEquals(c.selectedCurrency, 'USD');
//c.qObj = quot1;
c.proceed();
c.selectedCurrency = 'USD';
System.debug('%%%%%'+c.oppClone+'$$$$$'+c.selectedCurrency+'Opp OBj is:'+c.oppObj);
Test.setCurrentPage(new Pagereference('/apex/CloneOppNewCurrency?id='+quot1.Id));
CloneOppNewCurrencyController c1 = new CloneOppNewCurrencyController();
c1.selectedCurrency = 'None';
Pagereference pr = c1.cancel();
Test.stopTest();
}
}
Lines from 127 are not covered.The proceed method is not covered.Can anyone help me please?
What line does 127 correspond to in your example? Is it if(selectedCurrency!='None') { in the proceed() method?
I'd suggest to extend your exception handling. You basically have:
public void proceed() {
try {
// Most of method body here
} catch(Exception e) {
}
}
It is likely that an exception has occured and has been ignored/lost due to the empty Exception handling. Minimally, write the exception out to the log:
} catch(Exception e) {
System.debug(LoggingLevel.Error, 'BANG! ' + e);
}
That may well reveal in the debug log where your test method is failing.