I have created a trigger which is dependant on a custom record type existing. In my test for the trigger, I want to ensure that when this record type doesn't exist the trigger throws the appropriate exception. Unfortunately I can't see how I can do this, as DML statements can't be performed on Record Types. The error message I am getting is: "DML not allowed on RecordType" see the trigger code below:

trigger SetMostRecent on Opportunity (before insert) {

        List<RecordType> recordType = [SELECT id FROM RecordType WHERE Name = 'foo' AND SobjectType = 'Opportunity' limit 1];

        Id recordTypeId; 
        if (recordType.size() > 0) { 

            recordTypeId = recordType[0].Id; 
        else {
            throw new MembershipTypeNotFoundException('blahblah'); 

My test class is as follows:

 static testMethod void myTest() {
    //Creates a valid opportunity. 
    Opportunity opp = Data.ValidOpp(); 
    RecordType type = [SELECT id, Name FROM RecordType WHERE Name = 'foo' AND SobjectType = 'Opportunity'];
    //Line which throws DML not allowed on RecordType
    delete type;
    //should now throw custom exception..
    insert opp; 


Does anyone know a way how I could get around this?


3 Answers 3


How about some indirection by setting the record type ID on a class that handles the insert. Then in the test class you just set it to null to simulate the record type id not being present. The key would be to only allow it to be set once.

I didn't actually test any of the code below, but it illustrates my point.

The handler class.

public class SetMostRecentHanlder {

    private static Id recTypeId;
    private static Boolean recTypeSet = false;

     * Sets the record type id if it hasn't been set during
     * the current transaction already.
    public static void setRecTypeId(Id rId) {
        if (!recTypeSet) {
            recTypeId = rId;
            recTypeSet = true;

     * Handles the before insert for opportunities.
     * If the recTypeId is not set then a MembershipTypeNotFoundException is thrown
    public static void handleBeforeInsert(List<Opportunity> newList) {
        if (recTypeId == null) {
            throw new MembershipTypeNotFoundException('blah blah blah');
        // Handle processing the newList some how...

The trigger:

trigger SetMostRecent on Opportunity (before insert) {
    List<RecordType> recordTypes = [
        SELECT id FROM RecordType 
        WHERE Name = 'foo' AND SobjectType = 'Opportunity' limit 1
    if (!recordTypes.isEmpty()) {
       // Remember, the recType will only get set if setter not called before.
    // could pass Trigger.newMap if need map instead

The test methods

static testMethod void testInsertWhenNoRecType() {
    Opportunity opp = Data.ValidOpp(); 
    try {
        insert opp;
    } catch (MembershipTypeNotFoundException expected) {
        System.assert(true, 'Expected to catch exception ' + expected);
static testMethod void testInsertWhenRecTypePresent() {
    // Don't set rec type, so that trigger will
    // set it to the value in the DB.
    Opportunity opp = Data.ValidOpp(); 
    insert opp;

    // Assert something here.
  • Sure! Glad to hear it worked out. Commented Aug 21, 2012 at 10:08

Wouldnt validating something that exists look more like this?

Boolean MyTypeExists=false;
for(RecordType myType:[SELECT id, Name FROM RecordType WHERE Name = 'foo' AND SobjectType = 'Opportunity']){
system.assertEquals(true,MyTypeExists,'who done it?'); 

you can't modify record types from apex. It's an UI change only thing.

  • Apologies, I have updated my question with the test I am trying to do.
    – Jim
    Commented Aug 19, 2012 at 22:36

Could you update the trigger code to be something similar to:

List<RecordType> myTypes = [SELECT id, Name FROM RecordType WHERE Name = 'foo' AND SobjectType = 'Opportunity']; 
if(myTypes.size()) == 0) throw new myCustomException('blahblahblah');

and then your test class could be something like:

List<RecordType> myTypes = new List<RecordType>();
system.assertEquals(new myCustomException('blahblahblah'), trappedCodeException);
  • Hi thanks for the answer, I have updated my question to include the code on the trigger as well. Hopefully that will clarify things abit.
    – Jim
    Commented Aug 20, 2012 at 0:43
  • 2
    I don't think this will be able to be tested in the exact way you describe, due to not being able to perform DML on RecordTypes. However, using @isTest(SeeAllData=false) in API 24+, you should be able to test this sufficiently by inserting the Opportunity, and in a try/catch block of the test method asserting that if allOps.size == 1 after the insert && the recordtype exists or, if allOps.size == 0 then asserting the custom exception was thrown && that particular recordtype doesn't exist.
    – Mikey
    Commented Aug 20, 2012 at 1:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .