2

I have a situation when an Opportunity is updated, but its owner is inactive. The record itself are fine. But I create a full duplicate of the Opportunity and change a few fields there (but not owner).
How to test this situation in Unit Tests?

I runAs Opportunity creation with active user. Then I set it to inactive by user01.IsActive = false;. Then I run update on Opportunity as another active user. But clone is created with owner, which should be inactive. It is in test method.
As I understand, Apex does not see that first user is not active anymore. It doesn't see it in triggers/classes.
While testing this manually I'm getting INACTIVE_OWNER_OR_USER error. But not in test.

Test method:

@isTest
static void closeWonInactiveOwnerOpportunity() {
  // ...

  Profile p = [SELECT Id FROM Profile WHERE Name='qqq'];
  User u01 = new User(Alias = 'aaa', Email='aaa@aaa.com',
    EmailEncodingKey='UTF-8', LastName='aaa', FirstName='aaa', LanguageLocaleKey='en_US',
    LocaleSidKey='en_US', ProfileId = p.Id,
    TimeZoneSidKey='America/Los_Angeles', UserName='aaa@aaa.com',
    IsActive = true
  );

  Opportunity contract01;
  System.runAs(u01) {
    // ...
    Account company01 = new Account(Name = 'bbb');
    insert company01;
    contract01 = new Opportunity(
      AccountId = company01.Id,
      // ...
    );
    insert contract01;
    // ...
    List<OpportunityLineItem> oliListToInsert = new List<OpportunityLineItem>();
    // ...
    insert oliListToInsert;
  }
  u01.IsActive = false;

  contract01 = [SELECT OwnerId FROM Opportunity WHERE Id = :contract01.Id];
  System.debug(LoggingLevel.ERROR, '\n\n\n --- Opportunity_IT - closeWonInactiveOwnerOpportunity - 1 --- \n'
    +'\n - u01: ' + u01
    +'\n - u01.Id: ' + u01.Id
    +'\n - u01.IsActive: ' + u01.IsActive
    +'\n - contract01: ' + contract01
    +'\n - contract01.OwnerId: ' + contract01.OwnerId
  +'\n\n');
  System.assertEquals(u01.Id, contract01.OwnerId);
  List<Opportunity> projects01 = [SELECT OwnerId, CreatedById FROM Opportunity WHERE Main_Opportunity__c = :contract01.Id];
  System.assertEquals(0, projects01.size());

  Profile p02 = [SELECT Id FROM Profile WHERE Name='www'];
  User u02 = new User(Alias = 'bbb', Email='bbb@aaa.com',
    EmailEncodingKey='UTF-8', LastName='bbb', FirstName='bbb', LanguageLocaleKey='en_US',
    LocaleSidKey='en_US', ProfileId = p02.Id,
    TimeZoneSidKey='America/Los_Angeles', UserName='bbb@aaa.com',
    IsActive = true
  );

  Test.startTest();

  System.runAs(u02) {
    contract01.StageName = 'Closed Won';
    update contract01;

    List<Opportunity> projects01 = [SELECT OwnerId FROM Opportunity WHERE zzz__c = :contract01.Id];
    System.assertEquals(1, projects01.size());
    System.debug(LoggingLevel.ERROR, '\n\n\n --- Opportunity_IT - closeWonInactiveOwnerOpportunity - 2 --- \n'
      +'\n - u01: ' + u01
      +'\n - u01.Id: ' + u01.Id
      +'\n - u01.IsActive: ' + u01.IsActive
      +'\n - projects01: ' + projects01
      +'\n - projects01.OwnerId: ' + projects01[0].OwnerId
      +'\n - u02: ' + u02
      +'\n - u02.Id: ' + u02.Id
      +'\n - projects01.CreatedById: ' + projects01[0].CreatedById
    +'\n\n');
    System.assertEquals(u02.Id, projects01[0].OwnerId);
    System.assertEquals(u02.Id, projects01[0].CreatedById);
  }

  Test.stopTest();
}
  • What happens if you try to update u01 after you make that inactive? – kurunve Aug 15 '17 at 11:36
  • System.DmlException: Update failed. First exception on row 0 with id 005g0000004YrSNAA0; first error: MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): User, original object: Product2: [] – Andrii Muzychuk Aug 15 '17 at 11:40
  • Strange, but on upsert u01; I get Error:(97, 5) DML not allowed on User on class save. – Andrii Muzychuk Aug 15 '17 at 11:40
  • 1
    Mixed dml means that you can not perform update DML on setup (aka user/role/group etc) and non setup (normal sObject) dml in same context. So, I suggest you next thing -- Create admin user, and 2 test users in @testSetup, then in test method, under runAs for admin user create account/opp records, assigned to user1, then disable user 1, then login as user2 and perform dml on previously created records – kurunve Aug 15 '17 at 11:57
  • 1
    I managed the test by creating Opportunity in @testSetup and updating user in @isTest. – Andrii Muzychuk Aug 15 '17 at 11:58
0

I ended up separating creation of an Opportunity, which will then have inactive user and making user inactive and perform cloning of the Opportunity with inactive user. Creation is made in @testSetup, making user inactive and test itself are made in @isTest.

@IsTest
private class Opportunity_IT {

  static String CONTRACT_NAME = 'Contract 01';
  @testSetup
  static void testSetup() {
    // ...

    Profile p = [SELECT Id FROM Profile WHERE Name='qqq'];
    User u01 = new User(Alias = 'aaa', Email='aaa@aaa.com',
      EmailEncodingKey='UTF-8', LastName='aaa', FirstName='aaa', LanguageLocaleKey='en_US',
      LocaleSidKey='en_US', ProfileId = p.Id,
      TimeZoneSidKey='America/Los_Angeles', UserName='aaa@aaa.com',
      IsActive = true
    );

    Opportunity contract01;
    System.runAs(u01) {          
      Account company01 = new Account(Name = 'sss');
      insert company01;
      contract01 = new Opportunity(
        AccountId = company01.Id,
        // ...
      );
      insert contract01;

      List<OpportunityLineItem> oliListToInsert = new List<OpportunityLineItem>();
      // ...
      insert oliListToInsert;
    }

    contract01 = [SELECT OwnerId FROM Opportunity WHERE Name LIKE :CONTRACT_NAME];
    System.debug(LoggingLevel.ERROR, '\n\n\n --- Opportunity_IT - closeWonInactiveOwnerOpportunity - 1 --- \n'
      +'\n - u01: ' + u01
      +'\n - u01.Id: ' + u01.Id
      +'\n - u01.IsActive: ' + u01.IsActive
      +'\n - contract01: ' + contract01
      +'\n - contract01.OwnerId: ' + contract01.OwnerId
      +'\n\n');
    System.assertEquals(u01.Id, contract01.OwnerId);
    List<Opportunity> projects01 = [SELECT OwnerId, CreatedById FROM Opportunity WHERE ddd__c = :contract01.Id];
    System.assertEquals(0, projects01.size());
  }

  @isTest
  static void closeWonInactiveOwnerOpportunity() {

    Profile p02 = [SELECT Id FROM Profile WHERE Name='www'];
    User u02 = new User(Alias = 'bb', Email='bbb@aaa.com',
      EmailEncodingKey='UTF-8', LastName='bb', FirstName='bb', LanguageLocaleKey='en_US',
      LocaleSidKey='en_US', ProfileId = p02.Id,
      TimeZoneSidKey='America/Los_Angeles', UserName='bb@aaa.com',
      IsActive = true
    );

    Opportunity contract01 = [SELECT OwnerId FROM Opportunity WHERE Name LIKE :CONTRACT_NAME];
    User u01 = new User(Id = contract01.OwnerId, IsActive = false);
    update u01;

    Test.startTest();

    System.runAs(u02) {
      contract01.StageName = 'Closed Won';
      update contract01;

      List<Opportunity> projects02 = [SELECT OwnerId, CreatedById FROM Opportunity WHERE Main_Opportunity__c = :contract01.Id];
      System.assertEquals(1, projects02.size());
      System.debug(LoggingLevel.ERROR, '\n\n\n --- Opportunity_IT - closeWonInactiveOwnerOpportunity - 2 --- \n'
        +'\n - u01: ' + u01
        +'\n - u01.Id: ' + u01.Id
        +'\n - u01.IsActive: ' + u01.IsActive
        +'\n - projects01: ' + projects02
        +'\n - projects01.OwnerId: ' + projects02[0].OwnerId
        +'\n - u02: ' + u02
        +'\n - u02.Id: ' + u02.Id
        +'\n - projects01.CreatedById: ' + projects02[0].CreatedById
        +'\n\n');
      System.assertEquals(u02.Id, projects02[0].OwnerId);
      System.assertEquals(u02.Id, projects02[0].CreatedById);
    }

    Test.stopTest();
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.