You need to sign in to do that
Don't have an account?
Help with Test class
HI,
Below is the class and test class. It fine in UAT and gives no errors but iam not able to deploy it into production as it gives error as System.LimitException:Too many Query locator rows:10001
global class Visibility_Batch_BankAccount implements Database.Batchable<sObject> , Database.Stateful {
String query;
private Visibility_Utility vu;
global Database.QueryLocator start(Database.BatchableContext BC){
vu = new Visibility_Utility();
Visibility_Batch_Base vbb = new Visibility_Batch_Base('Bank_Account__c');
List<Integration_Info__c> intInfoList = [Select Last_Run_Time__c, Previous_Last_Run_Time__c from Integration_Info__c limit 1];
DateTime lastRunTime = intInfoList[0].Last_Run_Time__c;
DateTime PreviousLastRunTime = intInfoList[0].Previous_Last_Run_Time__c;
query = vbb.getQueryString();
return database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<sObject> scope){
vu.createShare('Bank_Account__c',scope);
}
global void finish(Database.BatchableContext BC){
}
}
and the test class is
@isTest
private class Visibility_Batch_BankAccount_Test{
static testMethod void Visibility_Batch_BankAccountTest(){
Visibility_Batch_BankAccount visBctBnkAcc = new Visibility_Batch_BankAccount();
Integration_Info__c ii = new Integration_Info__c();
ii.Previous_Last_Run_Time__c = System.Now().addMinutes(-1);
ii.Last_Run_Time__c = system.Now();
insert ii;
Bank_Account__c testBnkAcc = new Bank_Account__c(Name='testName');
List<Bank_Account__c> lstBnkAcc = new List<Bank_Account__c>();
lstBnkAcc.add(testBnkAcc);
insert lstBnkAcc;
Test.startTest();
visBctBnkAcc.start(null);
visBctBnkAcc.execute(null,lstBnkAcc);
visBctBnkAcc.finish(null);
Test.stopTest();
}
}
Thanks
Sure, System.IsRunningTest() simply returns true if the code is being executed as a test as opposed to being executed in a legitimate context by a user, so if you modify your handler class as follows you should be good to go:
public class IntergrationInfoHandler{
public static void initiateBatches(){
Visibility_Batch_Group vbg = new Visibility_Batch_Group();
Visibility_Batch_Party vbp = new Visibility_Batch_Party();
Visibility_Batch_BankAccount vbb = new Visibility_Batch_BankAccount();
Visibility_Batch_RelationshipGroup vbrg = new Visibility_Batch_RelationshipGroup();
if(!System.IsRunningTest()){
DataBase.ExecuteBatch(vbg);
DataBase.ExecuteBatch(vbp);
DataBase.ExecuteBatch(vbb);
DataBase.ExecuteBatch(vbrg);
}
}
}
All Answers
You should never rely on data from the database for your testmethods, instead be sure to always insert a record that your queries will find, and also use Test.IsRunningTest to determine if the code is being fired by a test method, if so you can then put a 'limit 1' or similar onto your query to ensure you don't get back masses of data.
In your case I would suggest that the query being returned by vbb.getQueryString() doesn't have a limit, and in your production environment you've got more than 10,000 rows of data in the Bank_Account__c object (assuming that's an object!) whereas in UAT you have less than 10,000.
Also be aware that you can only invoke the execute method once inside a batchable class in a test method so ensure the limit you use is smaller than the batch size (200 by default I believe).
Hi Matt
I changed my test class as below but its still giving errors as
Failure Message: "System.UnexpectedException: No more than one executeBatch can be called from within a testmethod. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.", Failure Stack Trace: "External entry point"
Not really sure what to do!!!!!
@isTest
private class Visibility_Batch_BankAccount_Test{
Profile p = [select id from profile where name='Rep Officer'];
User u = new User(alias = 'standt', email='standarduser@testorg.com',emailencodingkey='UTF-8', lastname='Testing',
languagelocalekey='en_US',localesidkey='en_US', profileid = p.Id,timezonesidkey='America/Los_Angeles',
username='stanr@testorg.com');
insert u;
static testMethod void Visibility_Batch_BankAccountTest(){
Visibility_Batch_BankAccount visBctBnkAcc = new Visibility_Batch_BankAccount();
Integration_Info__c ii = new Integration_Info__c();
ii.Previous_Last_Run_Time__c = System.Now().addMinutes(-1);
ii.Last_Run_Time__c = system.Now();
insert ii;
Bank_Account__c testBnkAcc = new Bank_Account__c(Name='testName');
List<Bank_Account__c> lstBnkAcc = new List<Bank_Account__c>();
lstBnkAcc.add(testBnkAcc);
insert lstBnkAcc;
Test.startTest();
System.runAs(u){
visBctBnkAcc.query = 'SELECT Id, Rep_Officer_Code__c, Account_Officer_Code__c, Office_Code__c FROM Bank_Account__c LIMIT 200';
visBctBnkAcc.start(null);
ID batchprocessid = Database.executeBatch(visBctBnkAcc);
visBctBnkAcc.finish(null);
}
Test.stopTest();
}
}
And by the way we do same data load both in UAT and Production daily. so the number of records are almost same in number in both UAT and Production. So not sure why its giving error in production and running fine in UAT.
Thanks
Hmmm, I can only see the one invocation of executeBatch, do you have another test method calling this one or anything? Or perhaps a trigger on insert of one of the objects that might be firing a batch?
Yes, I have 3 more test classes in similar way for objects named Parties (Accounts), Group__c, Relationship_Group__c and i have written the test classes as i wrote for Bank_Account__c object
And even i have trigger written on Integration_Info__c object . On the insert of the record into that object , the trigger fires and the batch apex classes runs
Ah ha!
The first part is fine, as they're separate test methods so won't impact each other. The one in the trigger is where you'll be coming unstuck.
My suggestion would be to call System.IsRunningTest() in the trigger, if it returns true then don't execute the batch there — that way when you try to invoke it later on in your test method it'll be for the first time and you should avoid the error.
Matt
Here is my trigger code
trigger runVisibilityBatch on Integration_Info__c(After insert, After update){
if(trigger.isAfter){
IntergrationInfoHandler.initiateBatches();
}
}
and the Handler class for that is
public class IntergrationInfoHandler{
public static void initiateBatches(){
Visibility_Batch_Group vbg = new Visibility_Batch_Group();
Visibility_Batch_Party vbp = new Visibility_Batch_Party();
Visibility_Batch_BankAccount vbb = new Visibility_Batch_BankAccount();
Visibility_Batch_RelationshipGroup vbrg = new Visibility_Batch_RelationshipGroup();
DataBase.ExecuteBatch(vbg);
DataBase.ExecuteBatch(vbp);
DataBase.ExecuteBatch(vbb);
DataBase.ExecuteBatch(vbrg);
}
}
I dont really know abt System.isRunningTest(). can u pls thow some more light on that or can u pls tell me where exactly shud i use that in my code
Thanks
Sure, System.IsRunningTest() simply returns true if the code is being executed as a test as opposed to being executed in a legitimate context by a user, so if you modify your handler class as follows you should be good to go:
public class IntergrationInfoHandler{
public static void initiateBatches(){
Visibility_Batch_Group vbg = new Visibility_Batch_Group();
Visibility_Batch_Party vbp = new Visibility_Batch_Party();
Visibility_Batch_BankAccount vbb = new Visibility_Batch_BankAccount();
Visibility_Batch_RelationshipGroup vbrg = new Visibility_Batch_RelationshipGroup();
if(!System.IsRunningTest()){
DataBase.ExecuteBatch(vbg);
DataBase.ExecuteBatch(vbp);
DataBase.ExecuteBatch(vbb);
DataBase.ExecuteBatch(vbrg);
}
}
}
Hi Matt,
Thanks for the Reply. But its saying system.IsRunningTest() method doesnot not exist. Instead i worte Test.IsRunningTest() and the class got saved but still its giving the error as
Failure Message: "System.UnexpectedException: No more than one executeBatch can be called from within a testmethod. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation."
just to make u clear , Here is all my code
Apex cbatch class for Bank_Account__c
global class Visibility_Batch_BankAccount implements Database.Batchable<sObject> , Database.Stateful {
global String query;
private Visibility_Utility vu;
global Database.QueryLocator start(Database.BatchableContext BC){
vu = new Visibility_Utility();
Visibility_Batch_Base vbb = new Visibility_Batch_Base('Bank_Account__c');
List<Integration_Info__c> intInfoList = [Select Last_Run_Time__c, Previous_Last_Run_Time__c from Integration_Info__c limit 1];
DateTime lastRunTime = intInfoList[0].Last_Run_Time__c;
DateTime PreviousLastRunTime = intInfoList[0].Previous_Last_Run_Time__c;
query = vbb.getQueryString();
return database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<sObject> scope){
vu.createShare('Bank_Account__c',scope);
}
global void finish(Database.BatchableContext BC){
}
}
Test class for it is
@isTest
private class Visibility_Batch_BankAccount_Test{
static testMethod void Visibility_Batch_BankAccountTest(){
Visibility_Batch_BankAccount visBctBnkAcc = new Visibility_Batch_BankAccount();
Integration_Info__c ii = new Integration_Info__c();
ii.Previous_Last_Run_Time__c = System.Now().addMinutes(-1);
ii.Last_Run_Time__c = system.Now();
insert ii;
Profile p = [select id from profile where name='Rep Officer' LIMIT 1];
User u = new User(alias = 'standt', email='standarduser@testorg.com',emailencodingkey='UTF-8', lastname='Testing',
languagelocalekey='en_US',localesidkey='en_US', profileid = p.Id,timezonesidkey='America/Los_Angeles',
username='stanr@testorg.com');
insert u;
Bank_Account__c testBnkAcc = new Bank_Account__c(Name='testName');
List<Bank_Account__c> lstBnkAcc = new List<Bank_Account__c>();
lstBnkAcc.add(testBnkAcc);
insert lstBnkAcc;
Test.startTest();
System.runAs(u){
visBctBnkAcc.query = 'SELECT Id, Rep_Officer_Code__c, Account_Officer_Code__c, Office_Code__c FROM Bank_Account__c LIMIT 1';
visBctBnkAcc.start(null);
ID batchprocessid = Database.executeBatch(visBctBnkAcc);
visBctBnkAcc.finish(null);
}
Test.stopTest();
}
}
and the handlet class for the trigger is
public class IntergrationInfoHandler{
public static void initiateBatches(){
Visibility_Batch_Group vbg = new Visibility_Batch_Group();
Visibility_Batch_Party vbp = new Visibility_Batch_Party();
Visibility_Batch_BankAccount vbb = new Visibility_Batch_BankAccount();
Visibility_Batch_RelationshipGroup vbrg = new Visibility_Batch_RelationshipGroup();
if(!Test.IsRunningTest()){
DataBase.ExecuteBatch(vbg);
DataBase.ExecuteBatch(vbp);
DataBase.ExecuteBatch(vbb);
DataBase.ExecuteBatch(vbrg);
}
}
}
I think iam lost now. Not really sure what exactly to do. Please help me on this its very urgent as im unable to deploy anything to prodution because the trigger has 0% code coverage
Thanks
Apologies for that, I always forget which of those classes it belongs to!
Code should be ok now, I'd say the next step is to run through the debug logs generated when you test the deployment, see if you can find the locations where database.executeBatch() is being invoked, and then follow back to see where else you may need a switch to prevent automatic execution from a trigger or similar.
Actually, looking at the error you've posted it would suggest that it uses the same message for calling executeBatch as it does for multiple invocations of the execute() method in your batch apex class.
You're using the default execute which expects a batch size of 200 records and you're specifying 'LIMIT 1' so that shouldn't be a problem. I'm check all of your other triggers etc. and the logs to see what else might be firing the batch. If you remove the call to execute from your test method does the test pass?
Matt
The test classes passed and was able to deploy to production. However iam getting only 60% of code coverage for the classes but got 100% coverage for the trigger. So i guess trigger coverage matters the most for deployment.
So Thankyou so much
The 75% requirement is an average across all of your code, if I were you I'd now run the tests in prod and see if you can work out what's causing the batch to be executed (without your explicit line there) — the higher you get your coverage the less pain you'll have during future deployments!