Apex class is called in a trigger based on some conditions.Test class passes the test but code coverage is stil 0% - apex

When work order updates to Completed then a new water meter reading record needs to created with two field values from work order and two from another object att. Both work order and water meter reading have a look up(workorder) and master detail relation(water meter reading) with att.Sorry for so much code,but I am really stuck and need help.
trigger CreateWaterMeterReading on sm1e__smWork_Order__c (after update)
{
if (Trigger.new.size() == 1)
{
sm1e__smWork_Order__c wo = Trigger.new[0];
if(wo.sm1e__WO_Type__c == 'Meter Read Move In/Out ' && wo.sm1e__Status__c == 'Completed')
reateNewWaterMeterRead.createWMRforMoveInOrOut(wo.Id);
}
}
--Apex class
public class CreateNewWaterMeterRead {
public static void createWMRforMoveInOrOut(string workorderId)
{
Work_Order__c wo = [Select Equipment__r.Name,Completion_Date__c,Meter_Reading__c from Work_Order__c where Id = : workorderId ];
Equipment__c att = [Select Id,Last_Water_Meter_Reading_Date__c,Last_Water_Meter_Reading__c from Equipment__c where Name = : wo.Equipment__r.Name ];
List<Water_Meter_Readings__c> newwmr = new List<Water_Meter_Readings__c>();
Water_Meter_Readings__c wmr = new Water_Meter_Readings__c();
wmr.Meter__c = att.Id;
wmr.Current_Meter_Reading__c = wo.Meter_Reading__c;
wmr.Current_Read_Date__c = wo.sm1e__Completion_Date__c;
wmr.Prior_Meter_Reading__c = att.Last_Water_Meter_Reading__c;
wmr.Prior_Read_Date__c = att.Last_Water_Meter_Reading_Date__c;
wmr.Source__c = 'Manual Read';
newwmr.add(wmr);
if(newwmr.size() >0)
insert newwmr;
}
--Test Class
isTest(SeeAllData = true)
public class CreateNewWaterMeterReadTest
{
static testmethod void createWMRforMoveInOrOut()
{
Work_Order__c wo = [Select Id,Equipment__r.Name,Completion_Date__c,Meter_Reading__c from Work_Order__c where sm1e__Status__c != 'Completed' AND sm1e__WO_Type__c = 'Meter Read Move In/Out' LIMIT 1];
Equipment__c att = [Select Id,Last_Water_Meter_Reading_Date__c,Last_Water_Meter_Reading__c from Equipment__c where Name = : wo.Equipment__r.Name ];
test.startTest();
wo.Meter_Reading__c = 1317;
wo.sm1e__Status__c = 'Completed';
update wo;
test.stopTest();
System.debug('updated wo');
Water_Meter_Readings__c wmr = new Water_Meter_Readings__c();
System.debug('wmr for test');
wmr.Meter__c= att.Id;
wmr.Current_Meter_Reading__c = wo.Meter_Reading__c;
wmr.Current_Read_Date__c = wo.Completion_Date__c;
System.debug('in between wmr');
wmr.Prior_Meter_Reading__c = att.Last_Water_Meter_Reading__c;
wmr.Prior_Read_Date__c = att.Last_Water_Meter_Reading_Date__c;
wmr.Source__c = 'Manual';
insert wmr;

You've written trigger on after update. But in your test class you're inserting a record and not updating it. That is why your code coverage is 0%. Refer to this link
For executing trigger you must do dml operation for which you've written a trigger. Also you can invoke your class method from test class by creating its instance. Refer above link for the same.

Related

Can some one help me on below apex code i want to update this code as per governor limits

public static void updatecasefields(List<Case> lstcase) {
//List<Case> lstcase = new list<case>();
ID devRecordTypeId = Schema.SObjectType.Case.getRecordTypeInfosByDeveloperName().get('CRM_CSR_Case').getRecordTypeId();
for (Case cs: lstcase) {
if(cs.ID != null && cs.RecordTypeId == devRecordTypeId) {
}
List<CRM_CasePick__c> Casp = [SELECT Id, CRM_Carrier_Name__c,CRM_LOB__c, CRM_SLA_Turnaround_Time__c,CRM_Category__c, CRM_Issue_Sub_Type__c,CRM_Issue_Type__c,CRM_Turnaround_Time_Days__c FROM CRM_CasePick__c WHERE CRM_Carrier_Name__c = :cs.GiDP_CarrierName__c AND CRM_Category__c = :cs.CRM_Category__c AND CRM_Issue_Type__c = :cs.CRM_Issue_Type__c AND CRM_Issue_Sub_Type__c = :cs.CRM_Issue_Sub_Type__c AND CRM_LOB__c = :cs.CRM_Line_of_Business__c];
for(CRM_CasePick__c CP: Casp) {
cs.CRM_Turnaround_Time_Days__c = cp.CRM_Turnaround_Time_Days__c;
cs.CRM_SLA_Turnaround_time__c = cp.CRM_SLA_Turnaround_Time__c;
}
}
}
Remove the SOQL query from the for loop - best practice is to never run a query within a loop.
Right now it is running that query for every value of the initial list. If the list is over 100 records, it will exceed the governor limit.

Test Class in apex

So i am new to salesforce and i finished my training and now im working on a project. But on my project i have stumbled on a test class that i am not finding a way to write it, so i would appreciate if anyone can help me figure out a way to write it. Here is the code:
public class AP01_Opportunity
{
//Method to create a new service contract when opportunity = Gagné
public static void CreateContract(List<Opportunity> listOpp, Map<Id, Opportunity> oldMap)
{
//Variable Declaration
ServiceContract sc;
List<ServiceContract> listSCToAdd = new List<ServiceContract>();
List<ContractLineItem> listContractItems = new List<ContractLineItem>();
List<Opportunity> listOppGagne = new list<Opportunity>();
//Loop in list of opportunities
for(Opportunity opp : listOpp)
{
if(opp.StageName == Label.ClotureGagne && !oldMap.get(opp.Id).isWon)
{
listOppGagne.add(opp);
}
}
//check if list has opportunity becoming won
if(listOppGagne.size() > 0){
Map<Id, Opportunity> mapOppGagne = new Map<Id, Opportunity> ([SELECT Id,
Name,
StageName,
Pricebook2Id,
Account.Name,
(SELECT Id,
PricebookEntryId,
PricebookEntry.Name,
Quantity,
UnitPrice
FROM OpportunityLineItems)
FROM Opportunity
WHERE Id in :listOppGagne]);
for( Opportunity opp : listOppGagne )
{
//Create new service contract
sc = new ServiceContract();
sc.Name = opp.Name;
sc.ApprovalStatus = Label.Activated;
sc.OpportunityId__c = Id.valueOf(opp.Id);
sc.Pricebook2Id = opp.Pricebook2Id;
sc.StartDate = Date.today();
listSCToAdd.add(sc);
}
if(listSCToAdd.size() > 0){
insert listSCToAdd;
Opportunity currentOpp;
ContractLineItem cli;
Id oppId;
for(ServiceContract servcont : listSCToAdd)
{
oppId = servcont.OpportunityId__c;
if(mapOppGagne.containsKey(oppId))
{
currentOpp = mapOppGagne.get(oppId);
//copy the oppLineItems per opportunity to the respective Service Contract
for(OpportunityLineItem items : currentOpp.OpportunityLineItems)
{
cli = new ContractLineItem();
cli.PricebookEntryId = items.PricebookEntryId;
cli.Quantity = items.Quantity;
cli.UnitPrice = items.UnitPrice;
cli.ServiceContractId = servcont.Id;
listContractItems.add(cli);
}
}
}
if(listContractItems.size() > 0)
{
insert listContractItems;
}
}
}
}
}
this code is a trigger that creates a new service contract record with contract line items copied from the opportunity line items, when the opportunity stage changes to "Cloturé Gagné" which means closed won in french.
Thank you in advance.
In order to write a simple test class I would recommend you to use the following guide: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_qs_test.htm
The idea is simple: Lets say you create an Opportunity in your Test class and make an insert or update in your case - your trigger class will automatically fire and run the code from your AP01_Opportunity class. You can put some
System.debug('some message');
to check if your logic works as expected and also which code blocks are executed

Test class for trigger

I just wrote this trigger and it seems to be working fine in dev, I need to move it into production, however, the test class I wrote passes the test but does not cover the trigger. Any help would be greatly appreciated. I am a bit green here. I know I should be inserting a contact (the account is a req field) then updating the contact field I just have no earthly clue how to do taht. Thank you
trigger PropOwned on Contact (after update) {
for (Contact c : Trigger.new) {
McLabs2__Ownership__c ownNew = new McLabs2__Ownership__c();
Contact oldContact = Trigger.oldMap.get(c.id);
if (c.One_Prop_Owned__c != oldContact.One_Prop_Owned__c && c.One_Prop_Owned__c != null) {
ownNew.McLabs2__Contact__c = c.id;
ownNew.McLabs2__Property__c = c.One_Prop_Owned__c;
insert ownNew;
}
}
}
This is the test class I wrote.
#isTest
public class TestOwnership {
static testMethod void createOwnership() {
McLabs2__Ownership__c ownNew = new McLabs2__Ownership__c();
ownNew.McLabs2__Contact__c = 'Michael Webb';
ownNew.McLabs2__Property__c = '131 West 33rd Street';
insert ownNew;
}
}
Your test class just creates a McLabs2__Ownership__c object and inserts this object in database. As a result of this trigger on McLabs2__Ownership__c(if exist) will be invoked, but you have to test a trigger on Contact object. Thus you need to insert an account and after that update it because your contact trigger works in after update mode.
So, you need something like that
#isTest
private class TestOwnership {
static testMethod void whenContactUpdatedNewOwnershipIsInserted() {
// create contact, you have to replace 'value1' with appropriate data type
Contact contact = new Contact(name = 'Test Contact', One_Prop_Owned__c = 'value1');
insert contact;
contact.One_Prop_Owned__c = 'value2'; // you have to replace value2 with appropriate data type
update contact;
// in this place you should has only one record of McLabs2__Ownership__c in database, because in test context real data isn't visible
List<McLabs2__Ownership__c> ownerships = [SELECT Id, McLabs2__Contact__c, McLabs2__Property__c FROM McLabs2__Ownership__c];
System.assertEquals(1, ownerships.size());
System.assertEquals(contact.Id, ownerships[0].McLabs2__Contact__c);
System.assertEquals(contact.One_Prop_Owned__c, ownerships[0].McLabs2__Property__c);
}
}
Read the following articles which might be pretty useful for you:
Apex Trigger best practice
SOQL in loop

Test Coverage fails on before insert / before update Apex trigger

I have this very simple before insert / update trigger on Opportunity that auto-selects the Price Book based on a dropdown value containing Sales Office (State) location info.
Here's my Trigger:
trigger SelectPriceBook on Opportunity ( before insert, before update ) {
for( Opportunity opp : Trigger.new ) {
// Change Price Book
// New York
if( opp.Campus__c == 'NYC' )
opp.Pricebook2Id = PB_NYC; // contains a Pricebook's ID
// Atlanta
if( opp.Campus__c == 'ATL' )
opp.Pricebook2Id = PB_ATL; // contains another Pricebook's ID
}
}
Here's my Test Class:
#isTest (SeeAllData = true)
public class SelectPriceBookTestClass {
static testMethod void validateSelectPriceBook() {
// Pricebook IDs
ID PB_NYC = 'xxxx';
ID PB_ATL = 'xxxx';
// New Opp
Opportunity opp = new Opportunity();
opp.Name = 'Test Opp';
opp.Office__c = 'NYC';
opp.StageName = 'Quote';
// Insert
insert opp;
// Retrive inserted opportunity
opp = [SELECT Pricebook2id FROM Opportunity WHERE Id =:opp.Id];
System.debug( 'Retrieved Pricebook Id: ' + opp.Pricebook2Id );
// Change Campus
opp.Office__c = 'ATL';
// Update Opportunity
update opp;
// Retrive updated opportunity
opp = [SELECT Pricebook2id FROM Opportunity WHERE Id =:opp.Id];
System.debug( 'Retrieved Updated Pricebook Id: ' + opp.Pricebook2Id );
// Test
System.assertEquals( PB_ATL, opp.Pricebook2Id );
}
}
The test runs report 0% test coverage.
Also, on similar lines I have another before insert trigger that sets the Owner of an Event same as the Owner of the parent Lead. Here's the code:
trigger AutoCampusTourOwner on Event( before insert ) {
for( Event evt : Trigger.new ) {
// Abort if other kind of Event
if( evt.Subject != 'Visit' )
return;
// Set Owner Id
Lead parentLead = [SELECT OwnerId FROM Lead WHERE Id = :evt.WhoId];
evt.OwnerId = parentLead.OwnerId;
}
}
This, too, is causing 0% coverage - my guess is that it's got something to do with the for loops in both. I know I'm seriously flouting DML rules by invoking SOQL query inside a for loop, but for my purposes it should be fine as these Events are created manually and only one at a time - so there are no scopes of governor limits kicking in due to bulk inserts.
The code in both cases work 100%. Please suggest a fix for the test cases.
Have you tried trigger.old ?? My thinking is, when you update the office in your test class from NYC to ATL, the value 'NYC' will be in trigger.old, and that's what you want to check in your trigger.
I could be wrong since i'm new to apex too, but try it and let me know what happens.
For the first trigger don't do anything rather just create opportunity and execute like this.
Test class for SelectPriceBook
#isTest
private class TriggerTestClass {
static testmethod void selectPriceTest(){
Opportunity opps = new Opportunity(
Name= 'Test Opps',
CloseDate = System.today().addDays(30),
StageName = 'Prospecting',
ForecastCategoryName = 'Pipeline',
Office__c = 'NYC');
insert opps;
Opportunity opps2 = new Opportunity(
Name= 'Test Opps 2',
CloseDate = System.today().addDays(28),
StageName = 'Prospecting',
ForecastCategoryName = 'Pipeline',
Office__c = 'ATL');
insert opps2;
}
}
It will give you good test coverage and I don't know what are you trying to do in AutoCampusTourOwner!
i have test class for these
trigger ClientEmailTrigger on inflooens__Client_Email__c (after insert, after update, before insert, before update) {
ApexTriggerSettings__c setting = ApexTriggerSettings__c.getValues('Inflooens Trigger Settings');
if(setting != NULL && setting.ClientEmailTrigger__c == TRUE){
AuditTrailController objAdt = new AuditTrailController();
if(Trigger.isAfter){
if(Trigger.isUpdate){
System.debug('In Update Client Email Record');
objAdt.insertAuditRecord(Trigger.newMap, 'inflooens__Client_Email__c', Trigger.new.get(0).Id, Trigger.oldMap);
}
if(Trigger.isInsert){
objAdt.insertAuditRecord(Trigger.newMap, 'inflooens__Client_Email__c', null , null);
}
}
}
}

How do I test a trigger with an approval process?

I have a trigger which initiates an approval process when certain criteria are met:
trigger AddendumAfterIHMS on Addendum__c (after update) {
for (integer i = 0; i<Trigger.new.size(); i++){
if(Trigger.new[i].RecordTypeId != '012V0000000CkQA'){
if(Trigger.new[i].From_IHMS__c != null && Trigger.old[i].From_IHMS__c == null){
ID addendumId = Trigger.new[i].Id;
// Start next approval process
Approval.ProcessSubmitRequest request = new Approval.ProcessSubmitRequest();
request.setObjectId(addendumId);
Approval.ProcessResult requestResult = Approval.process(request);
}
}
}
}
It works perfectly, but now i need to create a test class for it. I have created a class which brings the code up to 75% coverage, which is the minimum, but I'm picky and like to have 100% coverage on my code. The test class I have now gets stuck on the line request.setObjectId(addendumId); and doesn't move past it. The error I receive is:
System.DmlException: Update failed. First exception on row 0 with id a0CV0000000B8cgMAC; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AddendumAfterIHMS: execution of AfterUpdate
Here is the test class that I have written so far, most of the class actually tests some other triggers, but the important line which is throwing the error is the very last line update addendumTierFeature;
#isTest
private class AddendumTest {
static testMethod void myUnitTest() {
// Query Testing Account, will need ID changed before testing to place into production
Account existingAccount = [SELECT Id FROM Account LIMIT 1];
Model__c existingModel = [SELECT Id FROM Model__c WHERE Active__c = TRUE LIMIT 1];
Pricebook2 existingPricebook = [SELECT Id,Name FROM Pricebook2 WHERE IsActive = TRUE LIMIT 1];
List<Contact> existingContacts = [SELECT Id,Name FROM Contact LIMIT 2];
Contact existingContactPrimary = existingContacts[0];
Contact existingContactSecondary = existingContacts[1];
Opportunity newOpportunity = new Opportunity(
Name = 'New Opportunity',
Account = existingAccount,
CloseDate = Date.today(),
Order_Proposed__c = Date.today(),
StageName = 'Branch Visit - Not Responding',
Opportunity_Follow_Up__c = 'Every 120 Days',
LeadSource = 'Farm Lists',
Source_Detail__c = 'FSBO',
Model_Name__c = existingModel.Id,
Processing_Fee__c = 100.50,
Site_State__c = 'OR',
base_Build_Zone__c = 'OR',
Pricebook_from_Lead__c = existingPricebook.Name
);
insert newOpportunity;
//system.assert(newOpportunity.Id != null);
ID newOppId = newOpportunity.Id;
OpportunityContactRole contactPrimary = new OpportunityContactRole(
Role = 'Primary',
IsPrimary = true,
OpportunityId = newOppId,
ContactId = existingContactPrimary.Id
);
OpportunityContactRole contactSecondary = new OpportunityContactRole(
Role = 'Primary',
IsPrimary = false,
OpportunityId = newOppId,
ContactId = existingContactPrimary.Id
);
insert contactPrimary;
insert contactSecondary;
newOpportunity.Name = 'Different - Updating';
newOpportunity.Order_Accepted__c = Datetime.now();
update newOpportunity;
Addendum__c addendumCustomOption = new Addendum__c(
RecordTypeId = '012V0000000CkQA', //Pre Priced Custom Option
Opportunity__c = newOppId,
Item_Pre_Priced_Description__c = 'a1eV00000004DNu',
Reason__c = 'This is a reason',
Item__c = 'This is an Item',
Quantity__c = 1
);
Addendum__c addendumTierFeature = new Addendum__c(
RecordTypeId = '012V0000000Cjks', //Tier Feature
Opportunity__c = newOppId,
Category__c = 'Countertops',
Reason__c = 'This is a reason',
Item__c = 'This is an Item',
Quantity__c = 1
);
insert addendumCustomOption;
insert addendumTierFeature;
addendumCustomOption.Quantity__c = 2;
addendumTierFeature.Quantity__c = 2;
update addendumCustomOption;
update addendumTierFeature;
update newOpportunity;
addendumTierFeature.To_IHMS__c = system.now();
update addendumTierFeature;
addendumTierFeature.From_IHMS__c = system.now();
update addendumTierFeature;
}
}
Any help on this matter would be greatly appreciated. I believe the problem is in the way I am testing the approval process start. Is there by chance a special testing function for this?
After fiddling around for a little while I discovered that the error was actually tied into my approval process. I kept digging into the error logs until I got to the error: caused by: System.DmlException: Process failed. First exception on row 0; first error: MANAGER_NOT_DEFINED, Manager undefined.: []. This phrase indicates that there is no one defined for the next step in my approval process.
When I created the opportunity, I did not set the owner and somehow this created an opportunity which had an owner without a manager. The addendum was also created without an owner/manager. So when I tried to launch the next approval process, there was no manager to send the approval to and an error was thrown.