web-dev-qa-db-ja.com

Apex v24.0でOpportunityLineItemの単体テストを行うときに、STANDARD_PRICE_NOT_DEFINEDを回避するにはどうすればよいですか?

どうやらSalesforce.comのApexのSpring'12/v24.0リリースの新機能は、単体テストが「実際の」データにアクセスできなくなったことです。したがって、(変更を正しく理解している場合)SOQLクエリは単体テストの過程で挿入されたオブジェクトのみを取得するようになりました。それでも、いくつかの制限があります。

いずれにせよ、これはOpportunityLineItemのテストをウィンドウの外に投げ出すようです。理由は次のとおりです。

  • PriceBookEntryIdなしでOpportunityLineItemを挿入することはできませんが、
  • 製品Xの標準価格表エントリがすでにない限り、製品Xの新しい価格表エントリを挿入することはできませんが、
  • すべてのテーブルと同様に、Pricebook2テーブルは単体テストの実行の開始時に事実上空であるため、テストデータには標準の価格表がありません。
  • Apexで標準価格表を作成する方法はありません

私はこれらの4つのポイントの少なくとも1つが間違っていることを本当に望んでいますが、これまでのところ、既存のユニットテストのバリエーションはそれらのいずれかが間違っていることを示していません。もちろん、これは私のユニットテストが機能しなくなったことを意味します。これは文字通り一晩で起こりました-テストは金曜日に私のサンドボックスでうまく実行されました、そして今それらは失敗します。

私は何かが足りないのですか、それともこれは新しいSFDCリリースのバグですか?

20
Ben Dunlap

まず、安心するために、seeAllDataフラグを廃止する予定はありません。私たちはあなたの下から敷物を引き出すつもりはありません。アペックステストでの標準価格表の作成については、よくわかりません。今日のプラットフォームでは、既存のデータなしでテストすることが難しい領域がいくつかあると確信しています。これが、seeAllDataフラグが存在する理由の1つです。今後数回のリリースで、これらのギャップを埋めようとしています。

12
Rich Unger

Summer 14で導入された新機能があり、Test.getStandardPricebookId()を使用して、SeeAllDataTrueに設定しなくても標準の価格表IDを取得できるようになりました。

14
Jason Hardy

私はちょうどこれに遭遇しました、そしてあなたの投稿は古いですが、それはグーグルでの最初の結果なので、私がしたことを共有したいと思いました。

私の基本的なアーキテクチャは、テストデータをその場で作成する方法としてユーティリティクラスを呼び出すテストクラスです(他の方法もありますが、これが私の習慣です)。

短縮版:

  • すべてのデータをtrueに設定
  • 標準価格表がアクティブであることを確認してください
  • 標準価格表の価格表エントリを追加します-アクティブとしてフラグを立てます
  • 価格表をテストするための価格表エントリを追加します-アクティブとしてフラグを立てます

テストクラス:

@isTest (seeAllData=true)
public with sharing class RMA_SelectLineItemsControllerTest {

    static testmethod void testBasicObjects() {
        Pricebook2 standard = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
        if (!standard.isActive) {
            standard.isActive = true;
            update standard;
        }

        Pricebook2 pb = RMA_TestUtilities.createPricebook();
        Product2 prod = RMA_TestUtilities.createProduct();
        PricebookEntry pbe = RMA_TestUtilities.createPricebookEntry(standard,pb,prod);
    }

}

ユーティリティメソッドは次のようになります(新しいPBEの周りにのみ表示されます)。

public static PricebookEntry createPricebookEntry (Pricebook2 standard, Pricebook2 newPricebook, Product2 prod) {
    System.debug('***** starting one');
    PricebookEntry one = new PricebookEntry();
    one.pricebook2Id = standard.id;
    one.product2id = prod.id;
    one.unitprice = 1249.0;
    one.isactive = true;
    insert one;
    System.debug('***** one complete, ret next');
    PricebookEntry ret = new PricebookEntry();
    ret.pricebook2Id = newPricebook.id;
    ret.product2id = prod.id;
    ret.unitprice = 1250.0;
    ret.isactive = true;
    insert ret;
    return ret;
}
3
ReidCarlberg

もう1つの回避策は、Test.isRunningTest()を使用してテストで実行されていることをトリガーに認識させることですが、このソリューションはベストプラクティスのポイントを見逃していると思います。これは、テストを事前に分離することの全体的なポイントであると私は信じています。既存のデータ。

おそらく、Salesforceは、コードがテストのコンテキストで実行されている場合、Pricebook2.isStandardフィールドを書き込み可能にすることができます。または、特定のStandard Price Bookレコードにユーザーおよびプロファイルと同じステータスを与える必要がありますか?

1
jevonearth
Please let me know if anyone has used  Test.getStandardPricebookId() and able to insert opportunity line item in test class. I tried this method with below mentioned code but got an error ": STANDARD_PRICE_NOT_DEFINED, No standard price defined for this product: []".

Note: I have seeAllData=false

ID standardPBID = Test.getStandardPricebookId();

            PriceBook2 pb = new PriceBook2();
            pb.name = 'GEW Water CMS';
            pb.isActive=true;
            insert pb;

Product2 prod= new Product2();
                prod.name='TestProd';
                prod.productcode='4568';
                prod.isActive=true;
                insert prod;



PricebookEntry standardPrice = new PricebookEntry(Pricebook2Id = standardPBID, Product2Id = prod.Id, UnitPrice = 10000, IsActive = true,  currencyISOCode='USD' );

                PriceBookEntry pbe= new PricebookEntry(pricebook2id=pb.id, product2id=prod.id,unitprice=2000, isActive=true, currencyISOCode='EUR');
                insert pbe;

                OpportunityLineItem oli = new OpportunityLineItem(OpportunityId = OppList[0].Id, pricebookentryid=pbe.id, UnitPrice = 100, Quantity = 1);
                insert oli; 
0
Anuj Kumar