Does addError() work outside of triggers?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







6















I moved a method that sets addError() from a trigger into a Helper class. As I started writing test code for it it seems like the addError() is not actually preventing DML operations for the records that get modified in the helper class.



The information from the SF SObject class page states:
Marks a trigger record with a custom error message and prevents any DML operation from occurring.



Does this mean that addError() will not work outside of a trigger class?



EDIT



Adding some sample code.



public class MyHelperClass() {
public static void someMethod(Opportunity opp) {
opp.My_Field__c.addError('Some error');
insert opp;
}
}


And sample test for it without any asserts:



@IsTest
private class MyHelperClass_Test() {
@IsTest
static void someTest() {
Opportunity opp = new Opportunity();
opp.Name = 'Some Name';
opp.StageName = 'Prospect';
opp.CloseDate = Date.today().addDays(30);

MyHelperClass.someMethod(opp);
}
}


The above inserts the opportunity and does not trigger an exception. Am I doing something wrong?










share|improve this question

























  • addError works in Visualforce controllers, Visualforce extensions, and anywhere within a Trigger context. It might be you simply made a mistake somewhere; it won't block DML operations on records not involved in Trigger.new or Trigger.old (for delete events only). We probably need to see the actual code to help you.

    – sfdcfox
    May 14 at 16:09













  • @sfdcfox I added sample code. Let me know if this makes more sense?

    – Arthlete
    May 14 at 16:15


















6















I moved a method that sets addError() from a trigger into a Helper class. As I started writing test code for it it seems like the addError() is not actually preventing DML operations for the records that get modified in the helper class.



The information from the SF SObject class page states:
Marks a trigger record with a custom error message and prevents any DML operation from occurring.



Does this mean that addError() will not work outside of a trigger class?



EDIT



Adding some sample code.



public class MyHelperClass() {
public static void someMethod(Opportunity opp) {
opp.My_Field__c.addError('Some error');
insert opp;
}
}


And sample test for it without any asserts:



@IsTest
private class MyHelperClass_Test() {
@IsTest
static void someTest() {
Opportunity opp = new Opportunity();
opp.Name = 'Some Name';
opp.StageName = 'Prospect';
opp.CloseDate = Date.today().addDays(30);

MyHelperClass.someMethod(opp);
}
}


The above inserts the opportunity and does not trigger an exception. Am I doing something wrong?










share|improve this question

























  • addError works in Visualforce controllers, Visualforce extensions, and anywhere within a Trigger context. It might be you simply made a mistake somewhere; it won't block DML operations on records not involved in Trigger.new or Trigger.old (for delete events only). We probably need to see the actual code to help you.

    – sfdcfox
    May 14 at 16:09













  • @sfdcfox I added sample code. Let me know if this makes more sense?

    – Arthlete
    May 14 at 16:15














6












6








6








I moved a method that sets addError() from a trigger into a Helper class. As I started writing test code for it it seems like the addError() is not actually preventing DML operations for the records that get modified in the helper class.



The information from the SF SObject class page states:
Marks a trigger record with a custom error message and prevents any DML operation from occurring.



Does this mean that addError() will not work outside of a trigger class?



EDIT



Adding some sample code.



public class MyHelperClass() {
public static void someMethod(Opportunity opp) {
opp.My_Field__c.addError('Some error');
insert opp;
}
}


And sample test for it without any asserts:



@IsTest
private class MyHelperClass_Test() {
@IsTest
static void someTest() {
Opportunity opp = new Opportunity();
opp.Name = 'Some Name';
opp.StageName = 'Prospect';
opp.CloseDate = Date.today().addDays(30);

MyHelperClass.someMethod(opp);
}
}


The above inserts the opportunity and does not trigger an exception. Am I doing something wrong?










share|improve this question
















I moved a method that sets addError() from a trigger into a Helper class. As I started writing test code for it it seems like the addError() is not actually preventing DML operations for the records that get modified in the helper class.



The information from the SF SObject class page states:
Marks a trigger record with a custom error message and prevents any DML operation from occurring.



Does this mean that addError() will not work outside of a trigger class?



EDIT



Adding some sample code.



public class MyHelperClass() {
public static void someMethod(Opportunity opp) {
opp.My_Field__c.addError('Some error');
insert opp;
}
}


And sample test for it without any asserts:



@IsTest
private class MyHelperClass_Test() {
@IsTest
static void someTest() {
Opportunity opp = new Opportunity();
opp.Name = 'Some Name';
opp.StageName = 'Prospect';
opp.CloseDate = Date.today().addDays(30);

MyHelperClass.someMethod(opp);
}
}


The above inserts the opportunity and does not trigger an exception. Am I doing something wrong?







apex trigger adderror






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 14 at 16:15







Arthlete

















asked May 14 at 15:58









ArthleteArthlete

1,1541221




1,1541221













  • addError works in Visualforce controllers, Visualforce extensions, and anywhere within a Trigger context. It might be you simply made a mistake somewhere; it won't block DML operations on records not involved in Trigger.new or Trigger.old (for delete events only). We probably need to see the actual code to help you.

    – sfdcfox
    May 14 at 16:09













  • @sfdcfox I added sample code. Let me know if this makes more sense?

    – Arthlete
    May 14 at 16:15



















  • addError works in Visualforce controllers, Visualforce extensions, and anywhere within a Trigger context. It might be you simply made a mistake somewhere; it won't block DML operations on records not involved in Trigger.new or Trigger.old (for delete events only). We probably need to see the actual code to help you.

    – sfdcfox
    May 14 at 16:09













  • @sfdcfox I added sample code. Let me know if this makes more sense?

    – Arthlete
    May 14 at 16:15

















addError works in Visualforce controllers, Visualforce extensions, and anywhere within a Trigger context. It might be you simply made a mistake somewhere; it won't block DML operations on records not involved in Trigger.new or Trigger.old (for delete events only). We probably need to see the actual code to help you.

– sfdcfox
May 14 at 16:09







addError works in Visualforce controllers, Visualforce extensions, and anywhere within a Trigger context. It might be you simply made a mistake somewhere; it won't block DML operations on records not involved in Trigger.new or Trigger.old (for delete events only). We probably need to see the actual code to help you.

– sfdcfox
May 14 at 16:09















@sfdcfox I added sample code. Let me know if this makes more sense?

– Arthlete
May 14 at 16:15





@sfdcfox I added sample code. Let me know if this makes more sense?

– Arthlete
May 14 at 16:15










2 Answers
2






active

oldest

votes


















6














It only works on trigger context records, but it can be applied to those records outside of a trigger. You cannot call this method on a record which is not yet in a trigger context, then have the error carry through to the trigger context.



This code won't prevent DML:



Account record = new Account();
record.addError('You cannot insert this record');
insert record;


However, this code will:



trigger Account on Account (before insert)
{
PreventDml.validate(trigger.new);
}
public with sharing class PreventDml
{
public void validate(List<SObject> records)
{
for (SObject record : records)
{
record.addError('You cannot insert this record');
}
}
}


If you are trying to test this code, the only realistic, effective way to make sure it does what you want is to run the trigger. For example, in this scenario I might have a test like:



@IsTest
class AccountTriggerTests
{
@IsTest static void testPreventDml()
{
DmlException expectedException;
Test.startTest();
try
{
insert new Account();
}
catch (DmlException dmx)
{
expectedException = dmx;
}
Test.stopTest();

system.assertNotEquals(null, expectedException,
'You should not be able to insert any Account');
system.assertEquals(0, [SELECT count() FROM Account],
'The database should be unchanged');
}
}





share|improve this answer


























  • That's very similar to my use case. How would you cover the line of code for record.addError('You cannot insert this record'); if you were to write test code for the PreventDml class alone? Is there a way to assert that the addError was set alone?

    – Arthlete
    May 14 at 16:33






  • 1





    @Arthlete Unlike other service methods, validation can only be effectively tested by running the trigger. There are hacks like checking ApexPages.hasMessages(), but they may not work in future releases, nor in all contexts even in the current release.

    – Adrian Larson
    May 14 at 16:44













  • Thank you, I will remember this!

    – Arthlete
    May 14 at 16:46



















4














addError won't block future DML operations, only those already in progress. You can use addError in any class, but it won't have any effect on future operations. As an example of what would work:



trigger myFieldBlock on Opportunity {
myFieldBlock.validate(Trigger.new);
}




public class myFieldBlock {
public static void validate(Opportunity records) {
records[0].My_Field__c.addError('Some error');
}
}




You can also use addError to display errors on a Visualforce page:



public class VFController {
public Account record { get; set; }
public VFController() {
record = new Account();
}
public void showError() {
record.Name.addError('Some error');
}
}




<apex:page controller="VFController">
<apex:form>
<apex:inputField value="{!record.Name}" />
<apex:commandButton value="Show Error" action="{!showError}" />
</apex:form>
</apex:page>





share|improve this answer
























  • i did not get this. We add addError in trigger to prevent DML operations from occurring. Your first snippet should prevent any DML operation on the record as its been called from Trigger Context. However in VF snippet even if there is any DML after we add error, it will execute.

    – Anshul Agrawal
    May 15 at 13:15














Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "459"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f262376%2fdoes-adderror-work-outside-of-triggers%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









6














It only works on trigger context records, but it can be applied to those records outside of a trigger. You cannot call this method on a record which is not yet in a trigger context, then have the error carry through to the trigger context.



This code won't prevent DML:



Account record = new Account();
record.addError('You cannot insert this record');
insert record;


However, this code will:



trigger Account on Account (before insert)
{
PreventDml.validate(trigger.new);
}
public with sharing class PreventDml
{
public void validate(List<SObject> records)
{
for (SObject record : records)
{
record.addError('You cannot insert this record');
}
}
}


If you are trying to test this code, the only realistic, effective way to make sure it does what you want is to run the trigger. For example, in this scenario I might have a test like:



@IsTest
class AccountTriggerTests
{
@IsTest static void testPreventDml()
{
DmlException expectedException;
Test.startTest();
try
{
insert new Account();
}
catch (DmlException dmx)
{
expectedException = dmx;
}
Test.stopTest();

system.assertNotEquals(null, expectedException,
'You should not be able to insert any Account');
system.assertEquals(0, [SELECT count() FROM Account],
'The database should be unchanged');
}
}





share|improve this answer


























  • That's very similar to my use case. How would you cover the line of code for record.addError('You cannot insert this record'); if you were to write test code for the PreventDml class alone? Is there a way to assert that the addError was set alone?

    – Arthlete
    May 14 at 16:33






  • 1





    @Arthlete Unlike other service methods, validation can only be effectively tested by running the trigger. There are hacks like checking ApexPages.hasMessages(), but they may not work in future releases, nor in all contexts even in the current release.

    – Adrian Larson
    May 14 at 16:44













  • Thank you, I will remember this!

    – Arthlete
    May 14 at 16:46
















6














It only works on trigger context records, but it can be applied to those records outside of a trigger. You cannot call this method on a record which is not yet in a trigger context, then have the error carry through to the trigger context.



This code won't prevent DML:



Account record = new Account();
record.addError('You cannot insert this record');
insert record;


However, this code will:



trigger Account on Account (before insert)
{
PreventDml.validate(trigger.new);
}
public with sharing class PreventDml
{
public void validate(List<SObject> records)
{
for (SObject record : records)
{
record.addError('You cannot insert this record');
}
}
}


If you are trying to test this code, the only realistic, effective way to make sure it does what you want is to run the trigger. For example, in this scenario I might have a test like:



@IsTest
class AccountTriggerTests
{
@IsTest static void testPreventDml()
{
DmlException expectedException;
Test.startTest();
try
{
insert new Account();
}
catch (DmlException dmx)
{
expectedException = dmx;
}
Test.stopTest();

system.assertNotEquals(null, expectedException,
'You should not be able to insert any Account');
system.assertEquals(0, [SELECT count() FROM Account],
'The database should be unchanged');
}
}





share|improve this answer


























  • That's very similar to my use case. How would you cover the line of code for record.addError('You cannot insert this record'); if you were to write test code for the PreventDml class alone? Is there a way to assert that the addError was set alone?

    – Arthlete
    May 14 at 16:33






  • 1





    @Arthlete Unlike other service methods, validation can only be effectively tested by running the trigger. There are hacks like checking ApexPages.hasMessages(), but they may not work in future releases, nor in all contexts even in the current release.

    – Adrian Larson
    May 14 at 16:44













  • Thank you, I will remember this!

    – Arthlete
    May 14 at 16:46














6












6








6







It only works on trigger context records, but it can be applied to those records outside of a trigger. You cannot call this method on a record which is not yet in a trigger context, then have the error carry through to the trigger context.



This code won't prevent DML:



Account record = new Account();
record.addError('You cannot insert this record');
insert record;


However, this code will:



trigger Account on Account (before insert)
{
PreventDml.validate(trigger.new);
}
public with sharing class PreventDml
{
public void validate(List<SObject> records)
{
for (SObject record : records)
{
record.addError('You cannot insert this record');
}
}
}


If you are trying to test this code, the only realistic, effective way to make sure it does what you want is to run the trigger. For example, in this scenario I might have a test like:



@IsTest
class AccountTriggerTests
{
@IsTest static void testPreventDml()
{
DmlException expectedException;
Test.startTest();
try
{
insert new Account();
}
catch (DmlException dmx)
{
expectedException = dmx;
}
Test.stopTest();

system.assertNotEquals(null, expectedException,
'You should not be able to insert any Account');
system.assertEquals(0, [SELECT count() FROM Account],
'The database should be unchanged');
}
}





share|improve this answer















It only works on trigger context records, but it can be applied to those records outside of a trigger. You cannot call this method on a record which is not yet in a trigger context, then have the error carry through to the trigger context.



This code won't prevent DML:



Account record = new Account();
record.addError('You cannot insert this record');
insert record;


However, this code will:



trigger Account on Account (before insert)
{
PreventDml.validate(trigger.new);
}
public with sharing class PreventDml
{
public void validate(List<SObject> records)
{
for (SObject record : records)
{
record.addError('You cannot insert this record');
}
}
}


If you are trying to test this code, the only realistic, effective way to make sure it does what you want is to run the trigger. For example, in this scenario I might have a test like:



@IsTest
class AccountTriggerTests
{
@IsTest static void testPreventDml()
{
DmlException expectedException;
Test.startTest();
try
{
insert new Account();
}
catch (DmlException dmx)
{
expectedException = dmx;
}
Test.stopTest();

system.assertNotEquals(null, expectedException,
'You should not be able to insert any Account');
system.assertEquals(0, [SELECT count() FROM Account],
'The database should be unchanged');
}
}






share|improve this answer














share|improve this answer



share|improve this answer








edited May 14 at 16:42

























answered May 14 at 16:23









Adrian LarsonAdrian Larson

113k19127267




113k19127267













  • That's very similar to my use case. How would you cover the line of code for record.addError('You cannot insert this record'); if you were to write test code for the PreventDml class alone? Is there a way to assert that the addError was set alone?

    – Arthlete
    May 14 at 16:33






  • 1





    @Arthlete Unlike other service methods, validation can only be effectively tested by running the trigger. There are hacks like checking ApexPages.hasMessages(), but they may not work in future releases, nor in all contexts even in the current release.

    – Adrian Larson
    May 14 at 16:44













  • Thank you, I will remember this!

    – Arthlete
    May 14 at 16:46



















  • That's very similar to my use case. How would you cover the line of code for record.addError('You cannot insert this record'); if you were to write test code for the PreventDml class alone? Is there a way to assert that the addError was set alone?

    – Arthlete
    May 14 at 16:33






  • 1





    @Arthlete Unlike other service methods, validation can only be effectively tested by running the trigger. There are hacks like checking ApexPages.hasMessages(), but they may not work in future releases, nor in all contexts even in the current release.

    – Adrian Larson
    May 14 at 16:44













  • Thank you, I will remember this!

    – Arthlete
    May 14 at 16:46

















That's very similar to my use case. How would you cover the line of code for record.addError('You cannot insert this record'); if you were to write test code for the PreventDml class alone? Is there a way to assert that the addError was set alone?

– Arthlete
May 14 at 16:33





That's very similar to my use case. How would you cover the line of code for record.addError('You cannot insert this record'); if you were to write test code for the PreventDml class alone? Is there a way to assert that the addError was set alone?

– Arthlete
May 14 at 16:33




1




1





@Arthlete Unlike other service methods, validation can only be effectively tested by running the trigger. There are hacks like checking ApexPages.hasMessages(), but they may not work in future releases, nor in all contexts even in the current release.

– Adrian Larson
May 14 at 16:44







@Arthlete Unlike other service methods, validation can only be effectively tested by running the trigger. There are hacks like checking ApexPages.hasMessages(), but they may not work in future releases, nor in all contexts even in the current release.

– Adrian Larson
May 14 at 16:44















Thank you, I will remember this!

– Arthlete
May 14 at 16:46





Thank you, I will remember this!

– Arthlete
May 14 at 16:46













4














addError won't block future DML operations, only those already in progress. You can use addError in any class, but it won't have any effect on future operations. As an example of what would work:



trigger myFieldBlock on Opportunity {
myFieldBlock.validate(Trigger.new);
}




public class myFieldBlock {
public static void validate(Opportunity records) {
records[0].My_Field__c.addError('Some error');
}
}




You can also use addError to display errors on a Visualforce page:



public class VFController {
public Account record { get; set; }
public VFController() {
record = new Account();
}
public void showError() {
record.Name.addError('Some error');
}
}




<apex:page controller="VFController">
<apex:form>
<apex:inputField value="{!record.Name}" />
<apex:commandButton value="Show Error" action="{!showError}" />
</apex:form>
</apex:page>





share|improve this answer
























  • i did not get this. We add addError in trigger to prevent DML operations from occurring. Your first snippet should prevent any DML operation on the record as its been called from Trigger Context. However in VF snippet even if there is any DML after we add error, it will execute.

    – Anshul Agrawal
    May 15 at 13:15


















4














addError won't block future DML operations, only those already in progress. You can use addError in any class, but it won't have any effect on future operations. As an example of what would work:



trigger myFieldBlock on Opportunity {
myFieldBlock.validate(Trigger.new);
}




public class myFieldBlock {
public static void validate(Opportunity records) {
records[0].My_Field__c.addError('Some error');
}
}




You can also use addError to display errors on a Visualforce page:



public class VFController {
public Account record { get; set; }
public VFController() {
record = new Account();
}
public void showError() {
record.Name.addError('Some error');
}
}




<apex:page controller="VFController">
<apex:form>
<apex:inputField value="{!record.Name}" />
<apex:commandButton value="Show Error" action="{!showError}" />
</apex:form>
</apex:page>





share|improve this answer
























  • i did not get this. We add addError in trigger to prevent DML operations from occurring. Your first snippet should prevent any DML operation on the record as its been called from Trigger Context. However in VF snippet even if there is any DML after we add error, it will execute.

    – Anshul Agrawal
    May 15 at 13:15
















4












4








4







addError won't block future DML operations, only those already in progress. You can use addError in any class, but it won't have any effect on future operations. As an example of what would work:



trigger myFieldBlock on Opportunity {
myFieldBlock.validate(Trigger.new);
}




public class myFieldBlock {
public static void validate(Opportunity records) {
records[0].My_Field__c.addError('Some error');
}
}




You can also use addError to display errors on a Visualforce page:



public class VFController {
public Account record { get; set; }
public VFController() {
record = new Account();
}
public void showError() {
record.Name.addError('Some error');
}
}




<apex:page controller="VFController">
<apex:form>
<apex:inputField value="{!record.Name}" />
<apex:commandButton value="Show Error" action="{!showError}" />
</apex:form>
</apex:page>





share|improve this answer













addError won't block future DML operations, only those already in progress. You can use addError in any class, but it won't have any effect on future operations. As an example of what would work:



trigger myFieldBlock on Opportunity {
myFieldBlock.validate(Trigger.new);
}




public class myFieldBlock {
public static void validate(Opportunity records) {
records[0].My_Field__c.addError('Some error');
}
}




You can also use addError to display errors on a Visualforce page:



public class VFController {
public Account record { get; set; }
public VFController() {
record = new Account();
}
public void showError() {
record.Name.addError('Some error');
}
}




<apex:page controller="VFController">
<apex:form>
<apex:inputField value="{!record.Name}" />
<apex:commandButton value="Show Error" action="{!showError}" />
</apex:form>
</apex:page>






share|improve this answer












share|improve this answer



share|improve this answer










answered May 14 at 16:24









sfdcfoxsfdcfox

273k14221472




273k14221472













  • i did not get this. We add addError in trigger to prevent DML operations from occurring. Your first snippet should prevent any DML operation on the record as its been called from Trigger Context. However in VF snippet even if there is any DML after we add error, it will execute.

    – Anshul Agrawal
    May 15 at 13:15





















  • i did not get this. We add addError in trigger to prevent DML operations from occurring. Your first snippet should prevent any DML operation on the record as its been called from Trigger Context. However in VF snippet even if there is any DML after we add error, it will execute.

    – Anshul Agrawal
    May 15 at 13:15



















i did not get this. We add addError in trigger to prevent DML operations from occurring. Your first snippet should prevent any DML operation on the record as its been called from Trigger Context. However in VF snippet even if there is any DML after we add error, it will execute.

– Anshul Agrawal
May 15 at 13:15







i did not get this. We add addError in trigger to prevent DML operations from occurring. Your first snippet should prevent any DML operation on the record as its been called from Trigger Context. However in VF snippet even if there is any DML after we add error, it will execute.

– Anshul Agrawal
May 15 at 13:15




















draft saved

draft discarded




















































Thanks for contributing an answer to Salesforce Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f262376%2fdoes-adderror-work-outside-of-triggers%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

He _____ here since 1970 . Answer needed [closed]What does “since he was so high” mean?Meaning of “catch birds for”?How do I ensure “since” takes the meaning I want?“Who cares here” meaningWhat does “right round toward” mean?the time tense (had now been detected)What does the phrase “ring around the roses” mean here?Correct usage of “visited upon”Meaning of “foiled rail sabotage bid”It was the third time I had gone to Rome or It is the third time I had been to Rome

Bunad

Færeyskur hestur Heimild | Tengill | Tilvísanir | LeiðsagnarvalRossið - síða um færeyska hrossið á færeyskuGott ár hjá færeyska hestinum