I saw some surprising behaviour when storing the iterator obtained from a Set<Id>
as a member in a Queueable
class. So, I wrote the following trivial Queueable
class to investigate:
public class QueueableWithIterators implements Queueable {
public static List<String> results = new List<String>();
private Iterator<String> myIterator;
public QueueableWithIterators(Iterator<String> myIterator) {
this.myIterator = myIterator;
}
public void execute(QueueableContext param1) {
results.add(myIterator.next());
if(myIterator.hasNext()) {
System.enqueueJob(this);
}
}
}
The idea is that this Queueable
will exhaust the iterator, putting values onto a static list so that we can see the results in an Apex test.
Then I wrote a couple of tests:
@IsTest
private class QueueableWithIteratorsTest {
@IsTest
static void setVersion() {
Test.startTest();
System.enqueueJob(new QueueableWithIterators(new Set<String>{'a'}.iterator()));
Test.stopTest();
Assert.areEqual(1, QueueableWithIterators.results.size());
Assert.areEqual('a', QueueableWithIterators.results[0]);
}
@IsTest
static void listVersion() {
Test.startTest();
System.enqueueJob(new QueueableWithIterators(new List<String>{'a'}.iterator()));
Test.stopTest();
Assert.areEqual(1, QueueableWithIterators.results.size());
Assert.areEqual('a', QueueableWithIterators.results[0]);
}
}
Running these tests, the List
version passes but the Set
version fails. More than that, by looking at the code coverage state, we can see that the Set
version doesn't even run the execute()
method.
If I try to run this code in Anonymous Apex, the List
version completes and the Set
version job just gets stuck in Processing
status and never runs.
This smells like a bug, but is it a known issue (I couldn't find it) or a misunderstanding on my part?
NB, This is running in a Spring 23 scratch org.