I am new in Apex Development. I want to write a TestClass for my Apex Trigger.
I am sharing my code with you:
trigger ClosedOpportunityTrigger on Opportunity (before update) {
for(Opportunity o:Trigger.New) {
if(o.Probability==100 && o.Invoiced__c == true)
{
Attachment a = new Attachment();
try {
a = [Select Id, Name from Attachment where ParentId =:o.Id];
}
catch(Exception e) {
a = null;
}
if (a == null)
o.addError('Add an attachment before you close the Opportunity');
}
}
}
There are 2 things that need to be done :-
1. Create a record in 'Opportunity' object. Update it using code.
2. Create an attachment. Here is the link for your reference https://developer.salesforce.com/forums/?id=906F00000008yzKIAQ
Goodluck
public static void testmethod(){
opportunity opp = new opportunity()
//change whatever fields u need to make probability 100%
opp.stage = 'Closed Won';
opp.Invoiced__c == true;
try{
insert opp
}
catch(Exception e){
string errormessage = e.getMessage();
}
//now that u know how to do it, do a positive test where you also add an
//attachment
//as a side note, your catch block will never fire, because you aren't
//catching any exceptions you are just getting a null string
}
Related
I added the Apex Class and Apex trigger below to update the field Number_of_Contacts at the Account level when a Contact is added or removed to a certain Account.
My idea is to display in Accounts reports, how many Contacts an Account has. I had to do this, because Salesforce doesn't provide a Roll-Up Summary, at the Account level, to count Contacts.
I also tried creating a Flow, but it only works when a Contact is created or deleted.
Here are Apex Class and Trigger I tried to use:
Class:
public without sharing class ContactTriggerHandler {
private Set<Id> getAccountIds(List<Contact> contacts) {
Set<Id> accountIds = new Set<Id>();
for(Contact c : contacts) {
if(c.AccountId != null) {
accountIds.add(c.AccountId);
}
}
return accountIds;
}
private Map<Id, Account> getAccountMap(Set<Id> accountIds) {
return new Map<Id, Account>([SELECT Id, Number_of_Contacts__c FROM Account WHERE Id in :accountIds]);
}
public void process(List<Contact> contacts, System.TriggerOperation operation) {
Set<Id> accountIds = getAccountIds(contacts);
if(accountIds.size() > 0) {
Map<Id, Account> accountMap = getAccountMap(accountIds);
for(Contact c : contacts) {
if(accountMap.containsKey(c.AccountId)) {
switch on operation{
when AFTER_INSERT {
accountMap.get(c.AccountId).Number_of_Contacts__c += 1;
}
when AFTER_DELETE {
accountMap.get(c.AccountId).Number_of_Contacts__c -= 1;
}
when AFTER_UNDELETE {
accountMap.get(c.AccountId).Number_of_Contacts__c += 1;
}
}
}
}
update accountMap.values();
}
}
}
Trigger
trigger ContactTrigger on Contact (after insert, after delete, after undelete) {
ContactTriggerHandler handler = new ContactTriggerHandler();
switch on Trigger.operationType {
when AFTER_INSERT {
handler.process(Trigger.new, Trigger.operationType);
}
when AFTER_DELETE {
handler.process(Trigger.old, Trigger.operationType);
}
when AFTER_UNDELETE {
handler.process(Trigger.new, Trigger.operationType);
}
}
}
However, how can I include a line of code that updates the Number_of_Contacs__c field when a Contact moves to a different Account (like, an "After_Update" trigger)?
Thank you,
I tried some guidance on how to add AFTER UPDATE triggers in Apex Code, but I didn't succeed.
Trigger context variables give you access to old and new values, state of the database before the user clicked save and what the user has changed. You're passing from trigger to class only trigger.new but to get the id of original account the contact was linked to and update it - something like this.
Set<Id> idsToCheck = new Set<Id>();
// During update, only if account id changes...
for(Contact c : trigger.new){
Contact old = trigger.oldMap.get(c.Id);
if(c.AccountId != old.AccountId){
idsToCheck.add(c.AccountId);
idsToCheck.add(old.AccountId); // mark both for further processing
}
}
idsToCheck.remove(null);
List<Account> accounts = [SELECT Id, (SELECT Id FROM Contacts) FROM Account WHERE Id IN :idsToCheck];
for(Account a : accounts){
a.Number_of_Contacts__c = a.Contacts.size();
}
update accounts;
I have a managed bean that changes an attribute value and calls a popup.
I need also to commit the changes made (without having to click a commit button), I tried some code but it does nothing.
Help me, please.
DCBindingContainer bindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding operationBinding = bindings.getOperationBinding("Commit");
operationBinding.execute();
You can use the following functions to commit the change made to an Iterator programmatically (In an action listener for example) :
public static ViewObjectImpl getViewObjectFromIterator(String nomIterator) {
ViewObjectImpl returnVO = null;
DCBindingContainer dcb = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
if (dcb != null) {
DCIteratorBinding iter = dcb.findIteratorBinding(nomIterator);
if (iter != null) {
returnVO = (ViewObjectImpl)iter.getViewObject();
}
}
return returnVO;
}
private void commit(String IteratorName) {
ViewObject vo = this.getViewObjectFromIterator(IteratorName);
try {
vo.getApplicationModule().getTransaction().validate();
vo.getApplicationModule().getTransaction().commit();
} catch (ValidationException e) {
String validationErrorMessage = e.getDetailMessage();
//Occur when some committed data is rejected due to validation error.
//log it : log(Level.WARNING, " " + validationErrorMessage);
}
catch (Exception e) {
//Log it and warn something unexpected occured
}
}
//In your action listener simply call the commit function as follow
//You can Find YOUR_ITERATOR_NAME the your PageDef Binding file in the Executables Column
commit("YOUR_ITERATOR_NAME");
See more : https://gist.github.com/CedricL46/04570c1f078583321ad680ee8ba28f72
I am new to the automation world, I am trying to verfy an item in the list to see if it has been deleted or not.. I have used the following syntax but it says company found, which is not suppose to be the answer.. Please help
internal void verifycompany()
{
Thread.Sleep(1000);
int b = 1;
bool CompanyName = Driver.driver.FindElement(By.XPath(".//*[#id='companies']/tr[" + b + "]/td[1]")).Displayed;
if (CompanyName == false)
{
Console.WriteLine("company not found, test succesful");
Base.test.Log(LogStatus.Info, "company not found, test succesful");
}
else
{
b++;
Base.test.Log(LogStatus.Info, "Company found, test unscuccesful");
}
}
Unfortunately, isDisplayed does not return false if it is not displayed, it throws an exception stating that it couldn't be found (geez thanks).
What I did is create a reusable method where I can pass in an element and it'll throw it through a try catch and return true if found, or false if the exception is thrown.
Something like the below - I use java but it should help you figure out a way around your problem:
public boolean isDisplayed(WebElement webElement) {
try {
return element.isDisplayed();
} catch (NoSuchElementException e) {
return false;
}
}
If you don't want to create a reusable method, just throw your find element line into a try catch.
boolean CompanyName;
try {
CompanyName = findElementAndIsDisplayedCode;
} catch (NoSuchElementException e) {
CompanyName = false;
}
Is it possible to reserve an IDENTITY value for a to-be-added row in the database using Entity Framework?
In my override of ObjectContext.SaveChanges, I want to do something like this:
public override int SaveChanges(SaveOptions options)
{
var affectedEntities = ObjectStateManager.GetObjectStateEntries(
EntityState.Added |
EntityState.Modified |
EntityState.Deleted);
foreach (var entry in affectedEntities)
{
var type = GetObjectType(entry.Entity.GetType());
if (entry.State == EntityState.Added)
{
// log the creation of the new entity into a log file
// or a different table. For this, I need the newly
// created entity's ID. Is it possible?
}
}
return base.SaveChanges(options);
// if I check for ObjectState here, i.e. after SaveChanges,
// it won't work? Because once the changes are committed to the database
// the newly added object's state would no longer remain
// Added.
}
You can't ask the database to preallocate the id's. You have 2 options
implement your own identity server
get the id's after the data has been written to the database
Here's a couple of examples of option 2. They both do the same thing - build a list of added items before the call to SaveChanges() and iterate over them after.
public interface IIDentifiable
{
int id { get; set; }
}
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
List<IIDentifiable> addedObjects = GetNewEntries();
int result = base.SaveChanges();
foreach (IIDentifiable o in addedObjects)
{
//log o.id
}
return result;
}
private List<IIDentifiable> GetNewEntries()
{
var result = (
from e in ChangeTracker.Entries()
where e.State == System.Data.EntityState.Added
select e.Entity)
.OfType<IIDentifiable>()
.ToList();
return result;
}
the drawback of IIDentifiable is getting other details such as Type etc.
The second option is to do the same thing but use dynamic instead of IIDentifiable
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
List<dynamic> addedObjects = GetNewEntries();
int result = base.SaveChanges();
foreach (dynamic o in addedObjects)
{
//log o.id
//log o.GetType()
}
return result;
}
private List<dynamic> GetNewEntries()
{
var result = (
from e in ChangeTracker.Entries()
where e.State == System.Data.EntityState.Added
select e.Entity)
.ToList();
return result;
}
Trying to set a value for a roll up summary field in the test class to improve code coverage. How do I do it?
public class clsPreferredIASetExt {
List<PreferredIA__c> preferredias;
public static PreferredIA__c[] tobeClosed = new PreferredIA__c[0];
public static PreferredIA__c[] newPreIAs = new PreferredIA__c[0];
public static PreferredIA__c loopadd;
public static PreferredContact__c[] contactlists = new PreferredContact__c[0];
public static Account[] InvoicedAccounts = new Account[0];
public static PreferredIA__c[] monkey;
public clspreferrediaSetExt(ApexPages.StandardSetController controller) {
preferredias = (List<PreferredIA__c>) controller.getSelected();
}
public void getInitCloseInv() {
tobeclosed = [select id, Account__c, Account__r.id, Account__r.Name,
Account__r.AccountNumber, Specialist__c,
PreferredInvoice__c, Status__c
from PreferredIA__c where Status__c = 'Invoiced' limit 150];
list<string> testme = new list<string>{};
for(PreferredIA__c a:tobeclosed) {
testme.add(a.Account__r.id);
}
InvoicedAccounts = [select id, EligibleIAs__c, PreferredOverride__c,
Preferred_Territory__r.rep__c, LastSurveyDate__c,
InitialInspectionComplete__c, Program_level__c,
PreferredExempt__c, Account_Status__c,
Active_IAs__c, Last_Training__c
from Account where id IN :testme];
Contactlists = [select id, Account__c
from PreferredContact__c where Account__c IN :testme];
for(PreferredIA__c q:tobeclosed) {
q.Status__c = 'Closed';
}
for(Account z:invoicedaccounts) {
/****************************************************************
The following condition is where I am trying to set the z.EligibleIAs__c
which is a roll up count field of PreferredIA__c objects associated with
the account.
****************************************************************/
if(z.EligibleIAs__c == 0
&& z.Program_Level__c == 'Preferred'
&& !z.PreferredExempt__c
&& (z.Account_Status__c == 'Active'
|| z.Account_Status__c == 'Product Only')) {
loopadd = new PreferredIA__c();
system.debug(z.id);
system.debug(z.Account_Status__c);
loopadd.Account__c = z.id;
if(z.PreferredOverride__c != null) {
loopadd.Specialist__c = z.PreferredOverride__c;
}
else {
loopadd.Specialist__c= z.Preferred_territory__r.Rep__c;
}
for(PreferredContact__c q:contactlists) {
if(q.Account__c == z.id) {
loopadd.PreferredContact__c = q.id;
}
}
loopadd.CreatedDate__c = Date.Today();
if(z.Last_training__c != null) {
loopadd.DueDate__c = z.Last_Training__c.AddDays(365);
}
else {
loopadd.DueDate__c = Date.Today().AddDays(365);
}
loopadd.initial__c = false;
loopadd.Status__c = 'Unacknowledged';
newPreIAs.add(loopadd);
}
z.InitialInspectionComplete__c = true;
}
try {
update tobeclosed;
update invoicedaccounts;
insert newPreIAs;
}
catch(system.dmlexception q) {
system.debug(q);
system.debug(invoicedaccounts);
system.debug(newPreIAs);
}
}
public void ReceivePPW() {
monkey = [select id, Status__c from PreferredIA__c
where id in :preferredias and status__c = 'Training Completed'];
for (PreferredIA__c m:monkey) {
m.status__c = 'Awaiting Invoice';
}
update monkey;
}
}
I can't actually see where you're trying to write to the field — or did you remove it because it wasn't working?
That aside, the answer is that you can not write to a roll-up summary field. If you require a value in that field you should insert child records to your parent test records, with appropriate field values such that your summary field calculates a value.
Also, I can see that you're querying PerferredIA__c at the start, your test methods should never depend on data being in the system already, you should insert your records yourself in your test code. The reason for this is that if you try to deploy to an org which has no relevant data, your tests will fail and so, subsequently, will your deployment.
For situations like these, consider mock objects (or just variables simulating expected values), similar to inserting test values as Lacey suggests. This technique is required to achieve 100% coverage when doing callouts, for example, since they terminate tests at the moment of the call.