0

everyone. Im new to apex, I was trying for code coverage of atleast 75% on my batch apex code through test class. But im getting the error " System.QueryException: List has no rows for assignment to SObject ". Execute method is not covering in the code. Will anyone point out whats wrong with the testclass?

Batch Apex Class:-

Global class BatchApexOnAccount implements Database.Batchable<sObject> {
    Global Database.QueryLocator start (Database.BatchableContext Bc){
        return Database.getQueryLocator('Select Id, Name from Account');
    }
    Global void Execute(Database.BatchableContext Bc, List<Account> AccList){
        List<Account> AccEmpty = new List<Account>();
        for(Account Acc : AccList){
            Acc.Name = 'Salesforce';
            Acc.Description = 'Update Account ' + system.today();
            AccEmpty.add(Acc);
        }
        Update AccEmpty;
    }
    Global void Finish (Database.BatchableContext Bc){
        
    }
}

Test class:-

Test code

2 Answers 2

0

In your test class you have initiated Account but didn't insert, and in Line 21 you are querying the fields based on that account id which doesn't exists. Because of this you are getting the QueryException.

Sign up to request clarification or add additional context in comments.

Comments

0

Your test is weird. You select existing accounts. There are none. You have a piece of batch copy-pasted - why? Even if it'd work - how would you distinguish between what the test did and what the batch did?

You'd have to insert some accounts first. I think the error you get is from test's line 21 but the problems (including "Execute method is not covering in the code") are earlier.

Next time include the test's code too, screenshots are painful to retype.

I think you need something like this (there might be typos!)

private static void testBatch(){
   List<Account> accs = new List<Account>{
      new Account(Name = 'Unimportant'),
      new Account(Name = 'Whatever', Description = 'blah blah...')
   };
   insert accs;
   Test.startTest();
   Database.executeBatch(new BatchApexOnAccount());
   Test.stopTest();

   for(Account a : [SELECT Name, Description FROM Account]){
      System.assertEquals('Salesforce', a.Name);
      System.assert(a.Description.startsWith('Update account'));
   }
}

Edit: another user suggested following edit to my post. I don't agree with it but I'll put it here to preserve the idea and he can always post his own answer with improvements/reasoning.

https://stackoverflow.com/users/6718505/waldemar-liedle

All Assets (sic) in a Loop is a Bad Idea. When no Accounts are Inserted, the Test would still succeed. I would also Check something Outside Loop

   List<Account> testAccs = [SELECT Name, Description FROM Account];

   System.assertEquals(accs.size(), testAccs.size());

   for(Account a : testAccs){
      System.assertEquals('Salesforce', a.Name);
      System.assert(a.Description.startsWith('Update account'));
   }

So...

  • I don't think it matters because accounts are inserted earlier in the test. You'd need to completely mess the batch job up so it'd start deleting accounts for this query to fail finding any.
  • normally tests see only data that was inserted during test so it's not like it'll query thousands here (you'd run into other problems like "in test there can be only 1 execute()" so 200 accounts max)
  • in extreme cases querying all records to a List instead of looping through query (silently calling queryMore() when needed) will eat lots of memory

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.