0

I have written a bactch class which will delete old records, expect New 1000 records code shown below.

global class OldDataDeleterinAuditTrail implements DataBase.Batchable<sObject>{

     AuditTrail__c AuditRecords = [SELECT Id,CreatedDate  FROM AuditTrail__c ORDER BY CreatedDate DESC LIMIT 1 OFFSET 1000];   
    global DataBase.QueryLocator start(DataBase.BatchableContext bc)
    {
        return DataBase.getQueryLocator([SELECT Id,CreatedDate FROM AuditTrail__c WHERE CreatedDate <= :AuditRecords.CreatedDate]);
    }
    global void execute(DataBase.BatchableContext bc,List<AuditTrail__c> ListAT)
    {
        List<AuditTrail__c> ListAudit = new List<AuditTrail__c>();
        for(AuditTrail__c at : ListAT)
        {
            if(at.CreatedDate !=null) 
            {
                ListAudit.add(at);
                system.debug('-->>'+ListAudit);
            }
         } 
        if(ListAudit.size()>0)
        {
            delete ListAudit;
        }
    }
    global void finish(DataBase.BatchableContext bc)
    {

    }
}

and my test class shown below:

@isTest
public class OldDataDeleterinAuditTrailTest
    {
    Static TestMethod void olddatamethod()
    {
        AuditTrail__c a = New AuditTrail__c();
        a.Action__c = 'Add';
        a.CObjectName__c = 'Object Name';
        a.Description__c = 'will pass some query here';
        a.Status__c = 'Success';
        insert a;
        delete a;

        Test.StartTest();
        OldDataDeleterinAuditTrail AuditRecords = new OldDataDeleterinAuditTrail();
        Database.executeBatch(AuditRecords);
        Test.StopTest();
    }    
}

Test class error is:

System.QueryException: List has no rows for assignment to SObject Class.OldDataDeleterinAuditTrail.: line 4, column 1 Class.OldDataDeleterinAuditTrailTest.olddatamethod: line 15, column 1

if use Seealldata=True or false i getting following error: System.UnexpectedException: No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.

Help me if any have idea on this.

Thanks

6
  • You cannot fire SOQL in line 4. It should be in a method or constructor. Commented May 24, 2017 at 10:10
  • @MuzammilBajaria can you explain me how to do or any referance code to solve this?
    – user44771
    Commented May 24, 2017 at 10:19
  • did you tried deleting record after calling start test ?
    – Safiya PV
    Commented May 24, 2017 at 12:49
  • @blackPerlSAF can you please explain in detail?
    – user44771
    Commented May 24, 2017 at 13:27
  • I said to try with calling test.starttest() before delete a;
    – Safiya PV
    Commented May 24, 2017 at 13:29

3 Answers 3

2

I assume this question is related to: How to Delete Records in a object except Newly created 1000 Records by using Batch Class?

You can modify the approach laid out there to be easier to test by using lazy loading. That way, you can specify whatever date you want in your tests:

@TestVisible static Datetime threshold
{
    get
    {
        if (threshold == null)
        {
            threshold = [/*query*/].CreatedDate;
        }
        return threshold;
    }
    set;
}

Then, in your test, you can set the value and circumvent the query entirely:

MyBatch.threshold = Datetime.today().addMonths(-1);

You can also tweak your approach slightly so that it will work with less than 1000 records. In the above lazy load, change the code inside your assignment if block to the following:

List<MyObject__c> thresholdRecords = [
    SELECT CreatedDate FROM MyObject__c
    ORDER BY CreatedDate DESC
    LIMIT 1 OFFSET 1000
];
if (!thresholdRecords.isEmpty())
    threshold = thresholdRecords[0].CreatedDate;

Then, you can have your start method just return an empty list if there is no threshold set:

public Database.QueryLocator start(Database.BatchableContext context)
{
    if (threshold == null)
        return Database.getQueryLocator([
            SELECT Id FROM MyObject__c WHERE CreatedDate = null
        ]);
    return Database.getQueryLocator([
        SELECT Id FROM MyObject__c WHERE CreatedDate <= :threshold
    ]);
}
1
  • Thank you very much for your idea and support@Adrian Larson
    – user44771
    Commented May 25, 2017 at 7:49
1

Try using below code

 global DataBase.QueryLocator start(DataBase.BatchableContext bc)
{
   AuditTrail__c AuditRecords = [SELECT Id,CreatedDate  FROM AuditTrail__c 
                              ORDER BY CreatedDate DESC LIMIT 1 OFFSET 1000];   
    return DataBase.getQueryLocator([SELECT Id,CreatedDate FROM AuditTrail__c WHERE CreatedDate <= :AuditRecords.CreatedDate]);
}

Test Class

  @isTest
public class OldDataDeleterinAuditTrailTest
{
Static TestMethod void olddatamethod()
{
    List<AuditTrail__c> auditList = new List<AuditTrail__c>();
    for(integer i = 0;i<1001;i++){
    AuditTrail__c a = New AuditTrail__c();
    a.Action__c = 'Add';
    a.CObjectName__c = 'Object Name'+i;
    a.Description__c = 'will pass some query here'+i;
    a.Status__c = 'Success';
    auditList.add(a);
 }
    insert auditList;
    delete auditList.;

    Test.StartTest();
    OldDataDeleterinAuditTrail AuditRecords = new 
    OldDataDeleterinAuditTrail();
    Database.executeBatch(AuditRecords);
    Test.StopTest();
}    
}
1
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Adrian Larson
    Commented May 24, 2017 at 14:10
0

Use seaaAllData true and modify the below line

global DataBase.QueryLocator start(DataBase.BatchableContext bc)
{
    string query = 'SELECT Id,CreatedDate FROM AuditTrail__c WHERE CreatedDate <= :AuditRecords.CreatedDate ' +  (Test.isRunningTest()? 'Limit 50' :'');
    return DataBase.getQueryLocator(query);
}
3
  • Thanks Bharath for your suggestion,but i am getting this error: System.QueryException: Variable does not exist: AuditRecords.CreatedDate Class.ActiveCheckBox.start: line 8, column 1
    – user44771
    Commented May 24, 2017 at 10:30
  • 2
    You can't use dotted expressions in dynamic SOQL. Changing to dynamic SOQL won't change the query that is run. Also seealldata=true should be a last resort.
    – Keith C
    Commented May 24, 2017 at 12:28
  • @KeithC I have tried like that also.but not working.
    – user44771
    Commented May 24, 2017 at 13:26

You must log in to answer this question.