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
Aliaksei RazumauAliaksei Razumau 

Standard pricebook is not found in test class

In my test class I insert new products and pricebookentries, in my test class I don't use seeAllDate=true annotation and in order to retrieve standard pricebook id I used Test.getStandardPricebookId() method, here's my code:
Product2 p1 = new Product2(Name='Product Monthly 1111', Family='Monthly', isActive=true, CurrencyIsoCode='USD');
Product2 p2 = new Product2(Name='Product Yearly 2222', Family='Yearly', isActive=true, CurrencyIsoCode='USD');

insert new List<Product2>{p1, p2};

Id pricebookId = Test.getStandardPricebookId();

PricebookEntry pbe1 = new PricebookEntry(Pricebook2id=pricebookId, Product2id=p1.ID, isActive=true, CurrencyIsoCode='USD', unitPrice=100);
PricebookEntry pbe2 = new PricebookEntry(Pricebook2id=pricebookId, Product2id=p2.ID, isActive=true, CurrencyIsoCode='USD', unitPrice=50);

insert pbe1;
insert pbe2;

List<PricebookEntry> pbes = [SELECT ID FROM PricebookEntry 
    WHERE Product2id IN (:p1.Id, :p2.Id) AND Pricebook2.isStandard = TRUE AND Pricebook2.isActive = TRUE AND CurrencyIsoCode = 'USD' AND isActive = TRUE];

System.assertEquals(2, pbes.size());


pbes.size() returns 0. I used the same query in console for existing data and I got results. What am I doing wrong?
Amit Chaudhary 8Amit Chaudhary 8
Hi Aliaksei Razumau,

Please create PriceBookEntry and Pricebook2 record in your test class. like below :-
        Product2 prod = new Product2(Name = 'Laptop X200', 
                                     Family = 'Hardware');
        insert prod;
        
        Id pricebookId = Test.getStandardPricebookId();
        
        PricebookEntry standardPrice = new PricebookEntry(
            Pricebook2Id = pricebookId, Product2Id = prod.Id,
            UnitPrice = 10000, IsActive = true);
        insert standardPrice;
        
        Pricebook2 customPB = new Pricebook2(Name='Custom Pricebook', isActive=true);
        insert customPB;
        
        PricebookEntry customPrice = new PricebookEntry(
            Pricebook2Id = customPB.Id, Product2Id = prod.Id,
            UnitPrice = 12000, IsActive = true);
        insert customPrice;

Please mark this as solution by selecting it as best answer if this solves your problem, So that if anyone has this issue this post can help

 
Aliaksei RazumauAliaksei Razumau
Hi Amit,

thanks for your reply. If you looked at my code, I created everything you mentioned and have the same structure as you have. I want to use only standard pricebook and not custom, I used 
Id pricebookId = Test.getStandardPricebookId();

to get id of standard pricebook. But when I do a query I have no results returned. Maybe it's a problem with a query?
Aliaksei RazumauAliaksei Razumau
This is another query I ran which discover more insights:
List<PricebookEntry> pbez = [SELECT ID, Product2Id, Pricebook2.isStandard, Pricebook2.isActive, CurrencyIsoCode, isActive FROM PricebookEntry];

system.debug(pbez[0].Pricebook2.isStandard);
system.debug(pbez[0].Pricebook2.isActive);
In my code as mentioned before I used standard pricebook, but debuging returns both false results! I use almost same query in my trigger, so I can't really run any tests.. How is it possible? Are there workarounds? Maybe by using SeeAllDate=true?
Karol WodarczykKarol Wodarczyk
I believe this is a Apex limitation, and if there is no workaround just use "SeeAllData = ture" in the test instead
Ben EdwardsBen Edwards
A few years old now but I had the same issue and was able to fix it by first instantiating a new PriceBook2 with an Id of Test.getStandardPricebookId(), and then doing an update DML on the Pricebook2 record, and then linking the PriceBookEntry to it.

Eg...
// Instantiate the Pricebook2 record first, setting the Id
Pricebook2 standardPricebook = new Pricebook2(
	Id = Test.getStandardPricebookId(),
	IsActive = true
);

// Run an update DML on the Pricebook2 record
// This is the weird workaround that enables IsStandard to become true
// on the PricebookEntry record
update standardPricebook;

// Re-Query for the Pricebook2 record, for debugging
standardPricebook = [SELECT IsStandard FROM Pricebook2 WHERE Id = :standardPricebook.Id];

// This should return true now
system.assertEquals(true, standardPricebook.IsStandard, 'The Standard Pricebook should now return IsStandard = true');

// Create the Product
Product2 testProduct = new Product2(
	Name = 'Test Product', 
	IsActive = true
);
insert testProduct;

// Create the PricebookEntry
PricebookEntry testPbe = new PricebookEntry(
	Pricebook2Id = standardPricebook.Id,
	Product2Id = testProduct.Id,
	UnitPrice = 100,
	IsActive = true
);

insert testPbe;

// Re-Query the PBE
testPbe = [SELECT Id, Pricebook2.IsStandard FROM PricebookEntry];

// Should also return true
system.assertEquals(true, testPbe.Pricebook2.IsStandard, 'The Standard Pricebook should return true from the PBE as well.');

 
Andee Weir 17Andee Weir 17
Thanks so much Ben, saved me hours of frustration.
Vladimir Mir 1Vladimir Mir 1
Ben, You are a legend. Luckily I have spent only an hour before finding your solution.
It's friday and everyone sensible have left, apart from me beating this dead horse. Time to lock the office. Thanks!
BartKorziliusBartKorzilius
You got me out of a tough spot Ben, thanks!
Jayant Kumar JaiswalJayant Kumar Jaiswal
Super cool Ben. 
Please get this marked for correct solution.
Ron Mccrerey 20Ron Mccrerey 20
Thank you Ben. Your answer saved me a lot of frustration and time. I like your concise answer with a clear example. Yes, this needs to be marked as the correct solution.
Michael PaisnerMichael Paisner
This might also ne helpful to return standard pricebook id, depending on whether you are in a test class or not:
public static Id stdPricebookId = Test.isRunningTest() ? Test.getStandardPricebookId() : [SELECT id, name FROM Pricebook2 WHERE isStandard = true limit 1].Id;

 
Walter ParionaWalter Pariona
Thank you @Ben,  the DML update to the PriceBook2 object was the part I needed! Thanks for the good explanation.
Suraj Tripathi 47Suraj Tripathi 47
Hi Aliaksei,

You can fetch Standard Pricebook in test class by 
this way-:      
Pricebook2 standardPricebook = new Pricebook2(Id =        Test.getStandardPricebookId(),IsActive = true);
        update standardPricebook;
If you find your Solution then mark this as the best answer. 

Thank you!

Regards 
Suraj Tripathi
sfdc1.3890582999007844E12sfdc1.3890582999007844E12
@ben edwards thanks for your answer.. it was spot on!
Ashutosh Tiwari 65Ashutosh Tiwari 65

you need to update the Standard pricebook in @isTest class-

Id PricebookId = Test.getStandardPricebookId();
        PriceBook2 standardPriceBook=new PriceBook2(Id=PricebookId);        
        //pb.Id = PricebookId;
        update standardPriceBook;
Franz Anthony Rodriguez MaravíFranz Anthony Rodriguez Maraví
Does someone else get the following error during the update to StandardPricebook at test execution:
UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record:
 
Alan McQueenAlan McQueen
Ben Edwards answer was what I needed. What a curious object...