I wrote an apex trigger to update a field (status_update_date) when an account's status is changed.
In the sandbox, if I change an account's status, the status_update_date successfully updates.
When I run my test class, the trigger does not get called and I get a null value for the status_update_date. Any ideas why the trigger is not called? Thanks!
Code below with trigger commented out at bottom of code:
#isTest
private class UpdateStatusTest{
public static Account A;
public static String initStatus = '';
public static String finalStatus = 'Fully Active';
static testMethod void testWithAccount() {
A = new Account(
Status__c = initStatus,
Name = 'TestName'
);
insert A;
test.StartTest();
A.Status__c = finalStatus;
update A;
test.StopTest();
// System.assertEquals(finalStatus, A.Status__c);
System.assertEquals(system.today(),A.Status_Update_Date__c);
}
}
// trigger UpdateStatus on Account (before update) {
//for(Account a: trigger.new){
//If the status has changed, update the date
// if (trigger.oldMap.get(a.Id).Status__c != trigger.newMap.get(a.Id).Status__c) {
// a.Status_Update_Date__c = system.today();
// }
//}
//}
After update you should get this record from database by soql
a=[SELECT Id, Status__c FROM Account WHERE Id=:a.Id];
System.assertEquals(finalStatus, A.Status__c);
Related
I have created 20 records with the 'name=SampleAccountOne'. I am trying to create a batch class that will add a given contact to the 20 records. Stuck with syntax and where to go. Any help in the right direction is greatly appreciated.
global class UpdateProjectNameBatch implementsDatabase.Batchable<sObject> {
List<Contact> conList = new conList<Contact>();
String query = 'Select Id,Name FROM Account WHERE Name = \'SampleAccountOne\''
global Database.QueryLocator start(Database.BatchableContext bc){
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext bc,List<sObject> batch){
for(Contact c : conList){
batch.c = 'New Contact Name';
}
}
global void finish(){
}
}
I believe you are trying to associate a single contact to multiple accounts. This functionality was released in Spring 16' and is implemented through a Salesforce Junction object - AccountContactRelation.
I assume you have already enabled this functionality through the UI and a parent Account is declared for this Contact.
I have modified your code to associate the contact to all 20 account.
global class UpdateProjectNameBatch implements Database.Batchable
<sObject>
{ ID conId = '0037F00000IfCCKQA3'; //Add the contact Id here
List<AccountContactRelation> ListInsertion = new List<AccountContactRelation>();
String query = 'Select Id,Name FROM Account WHERE Name = \'SampleAccountOne\'';
global Database.QueryLocator start(Database.BatchableContext bc)
{
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext bc,List<Account> batch){
for (Account a : batch)
{
AccountContactRelation c = new AccountContactRelation();
c.AccountId = a.id;
c.contactId = conId;
ListInsertion.add(c);
}
Insert ListInsertion;
}
global void finish(Database.BatchableContext bc)
{
//DoNothing.
}
}
I wrote a static class that auto-increments the id of a RealmObject by 1.
public class AutoIncrementKey {
public static int Next(Class<? extends RealmObject> c)
{
Realm realm = Realm.getDefaultInstance();
Number maxId = realm.where(c).max("id");
realm.close();
if(maxId == null)
{ // no object exists, so return 0
return 0;
}
return maxId.intValue() + 1;
}
}
However, when I set the default value of a RealmObject's ID like so:
#PrimaryKey private int id = AutoIncrementKey.Next(PresetSelect.class);
It never works! Specifically the first time it goes to create a new class via realm.createObject(IExtendRealmObject.class) the value is 0, but AutoIncrementKey.Next(...) returns the id as 1!
So id is never set to 1. It's always 0, and trying to create more objects causes it to throw an error "index already exists: 0"
What gives?
The AutoIncrementKey.Next() function IS being called. It IS finding the next key to be 1. The value returned simply isn't carried through though.
Edit:
So now that I've managed to create more than one object in my Realm, I'm finding that setting the id to a default value isn't the only issue.
Setting ANY member of a class extending RealmObject with a default value is IGNORED. Whats the deal with that?
That's because instead of
realm.createObject(IExtendRealmObject.class)
You're supposed to use
realm.createObject(IExtendRealmObject.class, primaryKeyValue)
But I think your method
public class AutoIncrementKey {
public static int Next(Class<? extends RealmObject> c)
{
Realm realm = Realm.getDefaultInstance();
Number maxId = realm.where(c).max("id");
realm.close();
if(maxId == null)
{ // no object exists, so return 0
return 0;
}
return maxId.intValue() + 1;
}
}
Would be more stable as
public class AutoIncrementKey {
public static int Next(Realm realm, Class<? extends RealmModel> c)
{
Number maxId = realm.where(c).max("id");
if(maxId == null)
{ // no object exists, so return 0
return 0;
}
return maxId.intValue() + 1; // why not long?
}
}
If you meet the condition that when you call AutoIncrementKey.Next(realm, Some.class), then a write transaction is in progress.
Hell, you might even add
public class AutoIncrementKey {
public static int Next(Realm realm, Class<? extends RealmModel> c)
{
if(!realm.isInTransaction()) {
throw new IllegalStateException("Realm is not in a transaction.");
}
// continue as mentioned
It should work well for your needs
having a little trouble figuring out why my test class is returning System.DmlException: Upsert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Name]: [Name]
I have required field Name on the Account object in SFDC, but Since I'm mocking the Account with a Name attribute shouldn't my test class save function work?
Below is my Apex Class
public with sharing class QuoteAccountController {
// Define VariableType and VariableName
public ApexPages.StandardController standardContactController;
public Account Account{get;set;}
public Contact Contact{get;set;}
public Account selectedAccount{get;set;}
public Boolean displayProjectInformation{get;set;}
public Boolean projectNameError{get;set;}
public Boolean projectValidationsPassed{get;set;}
//Page Constructor/Initializer
public QuoteAccountController(ApexPages.StandardController StandardController) {
Account = new Account();
Contact = new Contact();
displayProjectInformation = true;
projectNameError = false;
projectValidationsPassed = true;
}
public pageReference save() {
projectValidations();
if (projectValidationsPassed) {
upsert Account;
Contact.accountId = Account.id;
upsert Contact;
Contact = new Contact();
Account = new Account();
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM,'Record Created Successfully.Thank you!'));
return null;
} else {
return null;
}
}
public void projectValidations(){
if (Account.Subscription_Type__c == 'Project' && String.isBlank(Account.Project_Name__c)) {
projectValidationsPassed = false;
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Project Name is required field'));
} else if (Account.Subscription_Type__c == 'Project' && String.isBlank(Account.Project_Type__c)) {
projectValidationsPassed = false;
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Project Type is required field'));
} else if (Account.Subscription_Type__c == 'Project' && Account.Project_Start_Date__c == null) {
projectValidationsPassed = false;
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Project Start Date is required field'));
} else if (Account.Subscription_Type__c == 'Project' && Account.Project_End_Date__c == null){
projectValidationsPassed = false;
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Project End Date is required field'));
} else {
projectValidationsPassed = true;
}
}
Below is my Apex Test Class
#isTest
public class QuoteAccountControllerTest {
private static testmethod void testSave() {
Quote quote = new Quote();
Account testAcc = new Account();
Contact con = new Contact();
ApexPages.StandardController stdCont = new ApexPages.StandardController(testAcc);
QuoteAccountController quoteAccCont = new QuoteAccountController(stdCont);
PageReference page = new PageReference('/apex/zqu_QuoteAccount?quoteType=Subscription&stepNumber=1');
Test.setCurrentPage(page);
testAcc.Project_Name__c = 'Project Name';
testAcc.Name = 'Test Account';
testAcc.Project_Start_Date__c = Date.today();
testAcc.Project_End_Date__c = Date.today().addDays(2);
testAcc.Project_Type__c = 'Convention Center';
testAcc.Region__c = 'US';
testAcc.Subscription_Type__c = 'User';
Test.startTest();
quoteAccCont.save();
Test.stopTest();
}
}
Thanks!
Edit: Error message below.
System.DmlException: Upsert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Name]: [Name]
I don't have too much background in Salesforce but I believe that you need to insert the objects that you are creating with new before Test.startTest();
If this fails too, try to use System.debug() in your Apex Test class and use the Salesforce developer console and their logs to follow your error. Maybe this helps. Good luck!
You are trying to upsert an account. Upsert(Update/Insert) call would look for Id in the account you are upserting. If Id is found Upsert would work fine else it would Insert. So in your case it is trying to insert not update. That is why Name is mandatory.
Figured out solution. Need to assign the Account and Contact to the Controller. See modified code below.
#isTest
public class QuoteAccountControllerTest {
private static testmethod void testSave() {
Quote quote = new Quote();
ApexPages.StandardController stdCont = new ApexPages.StandardController(testAcc);
QuoteAccountController quoteAccCont = new QuoteAccountController(stdCont);
quoteAccCont.Account = new Account(ATTRIBUTES_HERE);
quoteAccCont.Contact = new Contact(ATTRIBUTES_HERE
PageReference page = new PageReference('/apex/zqu_QuoteAccount?quoteType=Subscription&stepNumber=1');
Test.setCurrentPage(page);
Test.startTest();
quoteAccCont.save();
Test.stopTest();
}
}
Can anyone help me to create a test method for the following class. The basic idea of this code is to clone a patent with all child elements and just change the date.
public class NovoDia {
//added an instance varaible for the standard controller
private ApexPages.StandardController controller {get; set;}
// add the instance for the variables being passed by id on the url
private Itinerario_Diario__c po {get;set;}
private Itinerario_Diario__c pi {get;set;}
// set the id of the record that is created -- ONLY USED BY THE TEST CLASS
public ID newRecordId {get;set;}
// initialize the controller
public NovoDia(ApexPages.StandardController controller) {
//initialize the stanrdard controller
this.controller = controller;
// load the current record
po = (Itinerario_Diario__c)controller.getRecord();
}
// method called from the VF's action attribute to clone the po
public PageReference cloneWithItems() {
// setup the save point for rollback
Savepoint sp = Database.setSavepoint();
Itinerario_Diario__c newPO;
try {
//copy the purchase order - ONLY INCLUDE THE FIELDS YOU WANT TO CLONE
po = [select Dia__c from Itinerario_Diario__c where id = :po.id];
newPO = po.clone(false);
insert newPO;
// set the id of the new po created for testing
newRecordId = newPO.id;
// copy over the line items - ONLY INCLUDE THE FIELDS YOU WANT TO CLONE
List<Viagem__c> items = new List<Viagem__c>();
//PI.Dia__c = PO.Dia__c;
for (Viagem__c pi : [Select Cliente__c,Inicio_planejado__c,Entrada_Sa_da_de_Turno__c,Meio_de_Solicitacao__c,Motorista__c,Rota__c,Tipo_de_Viagem__c,Turno__c,Veiculo__c From Viagem__c p where Itinerario_Diario__c = :po.id ]) {
Viagem__c newPI = pi.clone(false);
newPI.Itinerario_Diario__c = newPO.id;
//newPI.Dia__c = PO.Dia__c;
items.add(newPI);
}
insert items;
} catch (Exception e){
// roll everything back in case of error
Database.rollback(sp);
ApexPages.addMessages(e);
return null;
}
return new PageReference('/'+newPO.id+'/e?retURL=%2F'+newPO.id);
}
I really appreciate the help.
Thanks
Sylvio
static testmethod void NovoDia_Test(){
Itinerario_Diario__c itinerarioDiario= new Itinerario_Diario__c();
insert itinerarioDiario;
ApexPages.StandardController sc = new ApexPages.StandardController(itinerarioDiario);
NovoDia cttr = new NovoDia (sc);
cttr.cloneWithItems();
}
I am wondering how do a mass update? I want to do a where clause and grab all items that meet that where clause Where(x => x.Id == 1).ToList() then do an update on all of them.
// change every name to bob
A.Name = "bob"
// then do a mass update
Do I have to do a foreach loop? And go through each one and then send it to be updated or is there another way to do this?
Thanks
Edit
I have this
// in my repo;
private readonly ISession session;
// session done with ninject IOC
public MyRepo(ISession session)
{
this.session = session;
}
public void MassUpdate(int id, string prefix)
{
var query = "UPDATE TableA SET Name= (:prefix) WHERE Id IN (:Id)";
session.CreateQuery(query).SetParameter("prefix", prefix).SetParameter("Id",Id);
}
public void Insert(MyClass myClass)
{
sesson.save(myClass);
}
public void Commit()
{
using (ITransaction transaction = session.BeginTransaction())
{
transaction.Commit();
}
}
// service layer method
public void myMethod()
{
MyClass myClass = nw MyClass() { Name = "test"};
MyRepo r = new Repo();
r.MassUpdate(1,"bob");
r.Insert(myClass);
r.Commit();
}
So how can I setup my MassUpdate to execute on Commit(). Note that this commit is used for all methods in MyRepo so I can't stick the execute in the commit method.
Expanding Diego's answer's, you can use HQL to send a list of arguments:
var person = 25;
var query = "update Foo set Name = 'bob' where id = :person";
var update = session.CreateQuery(query)
.SetParameter("person", person);
/***
*
* Do Stuff
*
***/
update.ExecuteUpdate();
session.CreateQuery("update Foo set Name = 'bob' where id = 1")
.ExecuteUpdate()
Sorry this is a late answer but just so you know a better solution (without query in plain text) exists here : Linq to Nhibernate Bulk Update Query Equivalent?
In your case it would be applied like this:
session.Query<TableA>().Where(f => f.Id == id)
.Update(i => new Foo { prefix = myPrefix });