Increase Code Coverage on Salesforce Standard Developer Test Case - salesforce

I need to increase code coverage on my test case. Right now, I am around 50%. I know that my extension is Account, but I somehow need to include Task info and Account.ParentId != Null and Task.Status =: 'Completed' into my test case somehow...Any help would be appreciated...
My Controller:
public class childTaskOnParentCont {
public Account acc {get;set;}
public List<Task> tasks {get;set;}
public List<Task> closedTasks {get;set;}
public List<Task> tasksLimited {get;set;}
public List<Task> closedTasksLimited {get;set;}
public List<Contact> cons {get;set;}
//constructor
public childTaskOnParentCont(apexpages.StandardController con){
acc = (Account) con.getRecord();
cons=[SELECT id from Contact WHERE AccountID=: acc.Id];
tasksLimited= [Select whoid,whatid,subject,type, Medium_of_Activity__c, activitydate, lastmodifieddate,Account.Name,
ownerid, status, priority from Task
Where Account.ParentID != null And status !='completed' ORDER BY activitydate LIMIT 10];
system.debug('taskslimited: '+taskslimited);
closedTasksLimited= [Select whoid,subject,type, Medium_of_Activity__c, activitydate, lastmodifieddate,Account.Name,
ownerid, status, priority from Task
Where Account.ParentID != null And status =:'completed' ORDER BY activitydate LIMIT 10];
system.debug('closedTasksLimited: '+closedTasksLimited);
}
//Get the Account Information
public Account getAccount() {
return [SELECT id,ParentId, name FROM Account WHERE Id=: acc.Id];
}
//Get Open Tasks for Child Tasks
public List<Task> getTasks() {
tasks= [Select whoid,subject,type, activitydate, lastmodifieddate,Account.Name,
ownerid, status, priority from Task
Where Account.ParentID != null And status !='completed' ORDER BY activitydate];
return tasks;
}
//Get Closed Tasks for Child Tasks
public List<Task> getClosedTasks() {
closedTasks= [Select whoid,subject,type, activitydate, lastmodifieddate,Account.Name,
ownerid, status, priority from Task
Where Account.ParentID != null And status =:'completed' ORDER BY activitydate];
return closedTasks;
}
}
My Test Case:
public class childTaskOnParentCont {
public Account acc {get;set;}
public List<Task> tasks {get;set;}
public List<Task> closedTasks {get;set;}
public List<Task> tasksLimited {get;set;}
public List<Task> closedTasksLimited {get;set;}
public List<Contact> cons {get;set;}
//constructor
public childTaskOnParentCont(apexpages.StandardController con){
acc = (Account) con.getRecord();
cons=[SELECT id from Contact WHERE AccountID=: acc.Id];
tasksLimited= [Select whoid,whatid,subject,type, Medium_of_Activity__c, activitydate, lastmodifieddate,Account.Name,
ownerid, status, priority from Task
Where Account.ParentID != null And status !='completed' ORDER BY activitydate LIMIT 10];
system.debug('taskslimited: '+taskslimited);
closedTasksLimited= [Select whoid,subject,type, Medium_of_Activity__c, activitydate, lastmodifieddate,Account.Name,
ownerid, status, priority from Task
Where Account.ParentID != null And status =:'completed' ORDER BY activitydate LIMIT 10];
system.debug('closedTasksLimited: '+closedTasksLimited);
}
//Get the Account Information
public Account getAccount() {
return [SELECT id,ParentId, name FROM Account WHERE Id=: acc.Id];
}
//Get Open Tasks for Child Tasks
public List<Task> getTasks() {
tasks= [Select whoid,subject,type, activitydate, lastmodifieddate,Account.Name,
ownerid, status, priority from Task
Where Account.ParentID != null And status !='completed' ORDER BY activitydate];
return tasks;
}
//Get Closed Tasks for Child Tasks
public List<Task> getClosedTasks() {
closedTasks= [Select whoid,subject,type, activitydate, lastmodifieddate,Account.Name,
ownerid, status, priority from Task
Where Account.ParentID != null And status =:'completed' ORDER BY activitydate];
return closedTasks;
}
}

Build your data, I don't see any test data
https://developer.salesforce.com/page/An_Introduction_to_Apex_Code_Test_Methods

To second #EricSSH -- you've got to make your tests actually run through your whole code by creating some data. The following trailhead was very helpful to me with Apex testing.
https://trailhead.salesforce.com/modules/apex_testing

Related

Getting dupicate agent names

Here am using map ,not abled to understand how to solve the duplicate name,i want one agent name against number of payments(child of opp)
how do I get unique names of users
public class First_Pay_ClearRates_Controller {
#AuraEnabled
public static Map<Id,User> fetchUsers() {
// List<User> userList= [SELECT Id, Name FROM User WHERE Profile.Name = 'Sales' LIMIT 20];
Map<Id,User> userMap= new Map<Id,User>([SELECT Id, Name FROM User WHERE Profile.Name = 'Sales' LIMIT 20]);
return userMap;
}
#AuraEnabled
public static List<Opportunity> getOpps(Map<Id,User> usrMap){
Map<Id,List<Opportunity>> oppMap = new Map<Id,List<Opportunity>>();
List<Opportunity> oppList = new List<Opportunity>();
List<Payments__c> payList= new List<Payments__c>();
List<Payments__c> payList1= new List<Payments__c>();
// prev key Agent_Name_User__c
// AND First_Payment_Date__c=THIS_MONTH
for(Opportunity o: [SELECT Id,First_Payment_Date__c,OwnerId,Owner.Name ,of_Payments_Made__c,PaymentsCounter__c,CollectedPaymentCount__c,First_Client_Payment_Collected_Date__c From Opportunity WHERE OwnerId IN: usrMap.keyset() AND First_Payment_Date__c!=null LIMIT 20]){
if(!oppMap.containsKey(o.OwnerId)){
oppMap.put(o.OwnerId,new List<Opportunity>());
}
o.PaymentsCounter__c=0;
o.CollectedPaymentCount__c=0;
//AND Due_Date__c=THIS_MONTH
for(Payments__c p :[Select Id,Opportunity__c,Payment_Collected__c,Due_Date__c FROM Payments__c WHERE Opportunity__c =: o.Id ]){
if(!p.Payment_Collected__c){
payList.add(p);
o.PaymentsCounter__c= payList.size();
}else if(p.Payment_Collected__c){
payList1.add(p);
o.CollectedPaymentCount__c= payList1.size();
}
}
oppList.add(o);
oppMap.put(o.OwnerId,oppList);
}
return oppList;
}

how to fix System.NullPointerException: Attempt to de-reference a null object in apex class using Map<parentId, child>?

Getting the error in line " taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;" becasue the ownerid field is on contact.
Contact is the parent of benefit, Here I am getting all the benefits in start method. I want to add contactid only once if it has more than one child for that I used SET. I want to use maps as I need to get the contact OwnerId field from contact object which I am fetching in the query in start method. How do I Access contact.ownerId field using a map? below is the code.
global Database.QueryLocator start(Database.BatchableContext bc) {
Query='select contact__r.ownerId, contact__c, Task_creation_date__c, Status__c, task_created__c, type__c from Benefit__c Where Task_creation_date__c= TODAY AND Status__c IN (\'Active\',\'Pending\') AND Task_created__c =FALSE AND Type__c!=\'Short Term Medical\'';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext bc, List<Benefit__c> scope){
// process each batch of records
List<Contact> contacts = new List<Contact>();
List<Task> TaskList = new List<Task>();
set<id> conset = New set<id>();
Map<id,benefit__c> ConMap = new map<id,Benefit__c>();
for (Benefit__c b : scope) {
conset.add(b.contact__c);
ConMap.put(b.contact__c, b);
b.task_created__c = TRUE;
}
system.debug('contact and its benefit------'+ConMap);
recordsProcessed = conset.size();
//List<Contact> tempList = new List<Contact>();
// tempList = [Select Id,OwnerId, firstname from Contact where Id IN:(conset)];
if(!ConMap.isEmpty())
{
for(Benefit__c ben : ConMap.values())
{
Task taskObj = new Task();
taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;
I want to populate contact ownerid as the task ownerid but how do I access it from the map and keep the unique contact id in the map?
I see that the batch query does not have the filtering condition 'Contact__c != null'. So, it's possible that one of the benefit records is missing value in the 'Contact__c' field and you wouldn't find it in the map. You can solve this in two ways:
Add 'Contact__c != null' to the selector query if you don't care about those records.
(Or)
Check for 'null' value in the for loop as below:
if(!ConMap.isEmpty())
{
for(Benefit__c ben : ConMap.values())
{
if(String.isBlank(ben.Contact__c)){
/* continue;
or
throw exception()
*/
}
Task taskObj = new Task();
taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;
I re wrote the code to resolve this nd optimize the code as below.
public with sharing class MyBatch implements Database.Batchable<AggregateResult>{
public Iterable<AggregateResult> start(Database.BatchableContext context)
{
return [
SELECT Contact__c, Contact__r.OwnerId owner FROM Benefit__c
WHERE Contact__c != null AND ...
GROUP BY Contact__c, Contact__r.OwnerId
];
}
public void execute(Database.BatchableContext context, List<AggregateResult> scope)
{
Set<Id> contactIds = new Set<Id>();
List<Task> tasks = new List<Task>();
for (AggregateResult aggregate : scope)
{
Id ownerId = (Id)aggregate.get('owner');
Id contactId = (Id)aggregate.get('Contact__c');
contactIds.add(contactId);
tasks.add(new Task(OwnerId=ownerId, /*other fields*/));
}
insert tasks;
List<Benefit__c> benefits = [
SELECT Id FROM Benefit__c WHERE Contact__c IN :contactIds
];
for (Benefit__c benefit : benefits)
benefit.Task_Created__c = true;
update benefits;
}
public void finish(Database.BatchableContext context) { /*additional logic*/ }}

To get the number of opportunities in an Account

how to count number of opportunities related to account,
total number of opportunities field on account should be increment/decrement when Opportunity is created/deleted.
How to solve it, pl help me with sample code.
Actually, you don't need write a code if you need count of all opportunities related to an account. Create a “Rollup/Summary” field type on the Account. Evaluate the Opportunity object, and run a “Count” operation. That’s it!
UPD:
If you need to solve it with trigger it will looks something like this:
trigger CountOpportunitiesOnAccount on Opportunity (after insert, after delete){
Set<Id> aId = new Set<Id>();
if(Trigger.isInsert || Trigger.isDelete || Trigger.isUndelete){
for(Opportunity opp : Trigger.New){
aId.add(opp.AccountId);
}
updateAccounts(aId);
}
if(Trigger.isDelete){
for(Opportunity opp : Trigger.old){
aId.add(opp.AccountId);
}
updateAccounts(aId);
}
private void updateAccounts(Set<Id> accIds){
List<Account> accs = [select id, OpportunitiesAmount from Account where Id in :accIds];
List<Opportunity> opps = [select id from Opportunity where AccountId in :accIds];
for(Account a : accs){
a.OpportunitiesAmount = opps.size();
}
update accs;
}
}
So, here you go. This is the Exact code that counts the Exact number of Related Opportunities of an Account and Populates it on the Standard field of Account Number ( you can add it on the custom field also).
trigger TriggTask on Opportunity (after insert, after delete)
{
List<id> TriggerList = new List<id>();
if(Trigger.isInsert)
{
List<id> TriggerList = new List<id>();
for(Opportunity Opp : Trigger.new)
{
TriggerList.add(Opp.AccountId);
}
List<Account> DML = New List<Account>();
List<Account> Ls = [select id,(select id from Opportunities) from Account where id in:TriggerList];
for(Account AccNew : ls)
{
Integer Num = AccNew.Opportunities.size();
AccNew.AccountNumber=String.valueOf(Num);
DML.add(AccNew);
}
update ls;
}
if(Trigger.isDelete)
{
for(Opportunity Opp : Trigger.old)
{
TriggerList.add(Opp.AccountId);
}
List<Account> DML = New List<Account>();
List<Account> Ls = [select id,(select id from Opportunities) from Account where id in:TriggerList];
for(Account act : Ls)
{
act.AccountNumber=String.valueOf(act.Opportunities.size());
DML.add(act);
}
update Ls;
}
}
If you must write a trigger, you might also consider the re-parenting of an Opportunity. This is why the Roll-Up Summary field is preferred by many developers. There may be edge cases that generate errors or unexpected results.
trigger CountOpportunitiesOnAccount on Opportunity (after insert, after delete, after update){
Set<Id> aId = new Set<Id>();
if(Trigger.isInsert || Trigger.isDelete || Trigger.isUndelete || Trigger.isUpdate){
for(Opportunity opp : Trigger.New){
if(Trigger.isUpdate){
if(Trigger.newMap.get(opp.Id).AccountID != Trigger.oldMap.get(opp.Id).AccountID){
aId.add(opp.AccountId);
}
}
else{
aId.add(opp.AccountId);
}
}
if(aID != NULL && aID.size() > 0){
updateAccounts(aId);
}
}
if(Trigger.isDelete){
for(Opportunity opp : Trigger.old){
aId.add(opp.AccountId);
}
updateAccounts(aId);
}
private void updateAccounts(Set<Id> accIds){
List<Account> accs = [select id, Number_Of_Opps__c, (select Id from Opportunities) from Account where Id in :accIds];
List<Account> liAccToUpdate = new list<Account>();
//Should be able to handle more than one opportunity/account in the trigger.
for(Account a : accs){
//Prevent recursive updating
if(a.Number_Of_Opps__c != a.Opportunities.size()){
a.Number_Of_Opps__c = a.Opportunities.size();
liAccToUpdate.add(a);
}
}
if(liAccToUpdate != NULL && liAccToUpdate.size() > 0){
update accs;
}
}
}
public static void opportunityCount(List<opportunity> oppList) {
set<id>accountIDs = new set<id>();
list<Account> accList = new List<Account>();
for (opportunity eachOppAccId:oppList) {
accountIDs.add(eachOppAccId.AccountId);
}
for (Account eachAccount:[select id,No_Of_Opportunities__c, (select id, AccountID from opportunities) from Account where id In:accountIDs]) {
eachAccount.No_Of_Opportunities__c=eachAccount.opportunities.size();
accList.add(eachAccount);
}
update accList;
}

Angular Web API $http post exclude list

I have a Web API (2) project which has departments and employees. An employee has a department, and a department has a list of employees.
Now in the frontend, when creating or editing an employee, the user must select a department. When posting this to the API, the department contains the list of employees (which causes an invalid modelstate), how can I prevent this?
This is my relevant setup:
Models:
public class Employee : IEntity, ICreatedOn, IModifiedOn, IMappable
{
[Key]
public virtual int Id { get; set; }
public virtual Department Department { get; set; }
// .. other properties
}
public class Department : IEntity, IMappable
{
[Key]
public virtual int Id { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
// .. other properties
}
Web API controller:
public class EmployeesController : ApiController
{
private readonly IEmployeeService _employeeService;
public EmployeesController(IEmployeeService employeeService)
{
this._employeeService = employeeService;
}
// .. GET, POST, DELETE etc.
// PUT: api/Employees/5
[ResponseType(typeof(void))]
public IHttpActionResult PutEmployee(int id, EmployeeVM employee)
{
// This is always invalid, because the employee has a department, which in turn has a list of employees which can be invalid
// What to do to exclude the list of employees from validation, or even better prevent from being sent to the API
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Update etc..
return StatusCode(HttpStatusCode.NoContent);
}
Angular (DataService.js):
app.factory('DataService',
["$http",
function ($http) {
return {
// other functions
updateEmployee: _updateEmployee
}
function _updateEmployee(employee) {
// Maybe exclude the list of employees in employee.department in here??
return $http.put(employeesUrl + "/" + employee.id, employee);
}
// .. other functions
}]);
Notes:
It happens in both the Put and the Post (updating and creating)
I'm using AutoMapper for mapping to the ViewModels, which look the same as the entities
I'm using Entity Framework for the ORM
What I've tried:
[JsonIgnore] attribute on the Employees collection; this causes the Employees also not being loaded when loading the Department
[Bind(Exclude = "Employees")] attribute in the controller action parameters, this did not have any effect
[Bind(Exclude = "Department.Employees")] same
What works, but I'm sure there must be a better solution:
function _updateEmployee(employee) {
var newEmp = angular.copy(employee);
delete newEmp.department.employees;
return $http.put(employeesUrl, newEmp);
}
Create a new request for updating your employee. Like:
public class UpdateEmployeeRequest{
public int EmployeeId {get;set;}
public int DepartmentId {get;set;}
//and so on
}
For this request you can specify concrete validation.
And declare Entities with explicit ID.:
public class Employee : IEntity, ICreatedOn, IModifiedOn, IMappable
{
[Key]
public int Id { get; set; }
[ForeignKey( "Department" )]
public Guid DepartmentId { get; set; }
[Required]
public virtual Department Department { get; set; }
// .. other properties
}
I would modify the Employee entity like this
public class Employee : IEntity, ICreatedOn, IModifiedOn, IMappable
{
[Key]
public virtual int Id { get; set; }
//Add DepartmentId
public Guid? DepartmentId { get; set; }
public virtual Department Department { get; set; }
// .. other properties
}
Then you can only set DepartmentId and that's it. EF will take care of the rest

Apex code-how to get the data of campaign Members from Subquery

I am trying to display four fields on my VF page Name, Status from (Campaign Members) and Subject and Last Modified Date from (Activity History) Object.I am not able to fetch the Name and Status fields from Campaign Members.
Can anyone please tell me How to get the Name and Status fields from Campaign Members.Below is my Controller code.
public with sharing class CampaignView {
public Campaign camp {get; set; }
public List<MemberWrapper> lMemberWrappers {get; set;}
public DateTime startDate {get; set;}
public CampaignView(ApexPages.StandardController controller) {
camp = (Campaign)controller.getRecord();
lMemberWrappers = new List<MemberWrapper>();
getCampaignMembers();
startDate = null;
for (Campaign c : [Select ID, (SELECT Id, CampaignId, Status FROM CampaignMembers where CampaignId = :camp.Id) FROM campaign WHERE id = :camp.Id ]) {
for (Lead ld : CampaignMembers) {
for (ActivityHistory ah : ld.getSObjects('ActivityHistories')) {
lMemberWrappers.add(new MemberWrapper(ld.Name, ah.Subject, ah.LastModifiedDate, ld.CampaignMembers.get(0).Status));
}
}
}
}
private List<Lead> CampaignMembers;
public List<Lead> getCampaignMembers() {
CampaignMembers = [Select Id, Name, Phone, MobilePhone, Email, LastModifiedDate, (Select id, Campaign.Name, Contact.Phone, Lead.FirstName, Lead.LastName, Lead.Name, LeadID, ContactID, Lead.Phone, Lead.Email, Lastmodifieddate, Lead.LastmodifiedDate, Status, CampaignId, Campign_ID__c, Lead.MobilePhone From CampaignMembers where CampaignId = :camp.Id ),
(Select Subject, Id, lastModifiedDate From ActivityHistories order by LastModifiedDate DESC LIMIT 1 )
From Lead where Id IN(select LeadId from campaignMember where campaignId = :camp.Id ) ];
return CampaignMembers;
}
public class MemberWrapper {
public Object Status {get; set;}
public String Name {get; set;}
public String Subject {get; set;}
public Datetime LastActivityHistory {get; set;}
public MemberWrapper(String Name, String Subject, Datetime LastActivityHistory, Object Status ) {
this.Name = Name;
this.Subject = Subject;
this.LastActivityHistory = LastActivityHistory;
this.Status = Status;
}
}
}
This will take you more than one query because of the ActivityHistory requirement. There are four levels of relationships in play here: Campaign -> CampaignMember -> Lead -> ActivityHistory, so you cannot perform this using just sub-queries.
The following code should get you the info you need:
Set<Id> leadIds = new Set<Id>();
List<Campaign> campaignList = [Select ID, (SELECT Id, Status, LeadId FROM CampaignMembers) FROM campaign WHERE id = :camp.Id ];
for (Campaign c : campaignList) {
for (CampaignMember cm : c.CampaignMembers) {
leadIds.add(cm.LeadId);
}
}
Map<Id, Lead> leadMap = new Map<Id, Lead>([Select Id, Name, (Select Subject, LastModifiedDate from ActivityHistories Order By LastModifiedDate DESC limit 1) From Lead Where Id IN :leadIds]);
for (Campaign c : campaignList) {
for (CampaignMember cm : c.CampaignMembers) {
Lead ld = leadMap.get(cm.LeadId);
if (ld.ActivityHistories.size() > 0) {
ActivityHistory ah = ld.ActivityHistories[0];
lMemberWrappers.add(new MemberWrapper(ld.Name, ah.Subject, ah.LastModifiedDate, cm.Status));
}
}
}
I just skipped creating the MemberWrapper if there were no activities, but you could change it to just put blank values if you wish.

Resources