function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
abhik dey 1abhik dey 1 

Last Login Date Issue in Test Class

I have created a batch APEX,

Below code

global class batchApexJob implements Database.Batchable<sObject> {
global Database.QueryLocator start(Database.BatchableContext BC) { String UsrQuery='';
UsrQuery = 'SELECT Id,isActive,LastLoginDate,Email,ManagerId FROM USER WHERE isActive = true AND LastLoginDate !=null'; return Database.getQueryLocator(UsrQuery);
}
global void execute(Database.BatchableContext BC, List<user> usrRecords) {
EmailTemplate etId=[Select id from EmailTemplate where name = 'ManagerEmail' limit 1];
if(usrRecords.size()>0){
for (User u : usrRecords){
if(System.now() > u.LastLoginDate.addDays(60)){
// for less than 90 days
system.debug('@@@'+u);
Messaging.MassEmailMessage mail = new Messaging.MassEmailMessage ();
mail.setTargetObjectIds(ids);
mail.setSenderDisplayName('Notification 1'); mail.setTemplateId(etId.id);
mail.setSaveAsActivity (false);
listofemails.add(mail);
Messaging.SendEmailResult[] r1 = Messaging.sendEmail(new Messaging.MassEmailMessage [] { mail });
}

while writing the test class for the same how to modfify the lastlogindate of the user, I dont see any methods availbale to change the last login date. After creating the user, is their any way i can change the last login date?
Is their any login attempts i can make and change the lastlogindate so that my batch class run.

Any Ideas to cover the batch class code coverage?
Shruti SShruti S
We cannot do anything in such a situation. We cannot set the Last Login date as it is a read only field. In such scenarios we should utilise the Test.isRunningTest() [returns a true if the code is being executed within a Test Context] method to set an alternate path for the Test Engine to cover our code. Below is the code which utilises Test.isRunningTest method - 
global class batchApexJob implements Database.Batchable<sObject> {
    global Database.QueryLocator start(Database.BatchableContext BC) { String UsrQuery='';
    UsrQuery = Test.isRunningTest() ? 'SELECT Id,isActive,LastLoginDate,Email,ManagerId FROM USER WHERE isActive = true' : 'SELECT Id,isActive,LastLoginDate,Email,ManagerId FROM USER WHERE isActive = true AND LastLoginDate !=null'
    return Database.getQueryLocator(UsrQuery)
}

global void execute( Database.BatchableContext BC, List<user> usrRecords ) {
    EmailTemplate etId=[
        Select  id 
        from    EmailTemplate 
        where   name = 'ManagerEmail' 
        limit 1
    ];
    
    if( usrRecords.size()>0 ){
        for ( User u : usrRecords ){
            if( Test.isRunningTest() || System.now() > u.LastLoginDate.addDays( 60 ) ) {
                // for less than 90 days
                system.debug( '@@@'+u );
                Messaging.MassEmailMessage mail = new Messaging.MassEmailMessage ();
                mail.setTargetObjectIds( ids );
                mail.setSenderDisplayName( 'Notification 1' ); mail.setTemplateId( etId.id );
                mail.setSaveAsActivity ( false );
                listofemails.add( mail );
                Messaging.SendEmailResult[] r1 = Messaging.sendEmail( new Messaging.MassEmailMessage [] { mail } );
}
Here are the changes I made -
  • In the start method, if it is running in test context then in the query we are not adding the 'LastLoginDate !=null' in the WHERE condition. So even if it is a test context, it will still fetch the records.
  • In the execute method, inside the for loop, I added an if condition in the for loop to check if it is a test context. So even if the LastLoginDate is empty, it will run the code below it since we are not lloking into the next condition in the if.
abhik dey 1abhik dey 1
@shruti: hmm thats the last option even i thought of. But to some reason I dont want to use test.isrunningtest(). On user login, is their event that i can capture, I see that the trigger doesn't run though it updates the LastLogindate of the user. 
Shruti SShruti S
I am sorry. None that I know of. I don't think there are events fired when the User logs in. And even if we have had since the "LastLoginDate" is read-only, I don't think we can set it :( 
abhik dey 1abhik dey 1
no worries