Open25

salesforce開発スクラップ

fukagawafukagawa

🔰 Salesforceの基本構成

1. CRMとは?

CRMは「顧客との関係を管理するシステム」。顧客情報、商談、サポート履歴などを一元管理し、営業やマーケティング、カスタマーサービスを強化します。

2. Salesforceの主要な製品

製品 主な用途
Sales Cloud 営業支援(リード管理、商談管理など)
Service Cloud カスタマーサポート(問い合わせ管理など)
Marketing Cloud マーケティングの自動化(メール、SNSなど)
Experience Cloud 顧客・パートナー向けポータル作成
Commerce Cloud ECサイトの構築・運用
Salesforce Platform カスタムアプリ開発(ノーコード/ローコード対応)


🧱 基本用語

用語 意味
オブジェクト(Object) 顧客や商談などのデータの種類(Excelで言う「シート」)
レコード(Record) 個々のデータ(Excelで言う「行」)
項目(Field) レコードの属性(Excelで言う「列」)
リード(Lead) 見込み客の情報
商談(Opportunity) 実際の販売活動
取引先(Account) 顧客会社などの情報
取引先責任者(Contact) 担当者(人)の情報


⚙️ 操作の基本フロー(Sales Cloudの例)

  1. リードを登録(例:展示会で得た名刺情報)
  2. リードを取引先・商談に変換
  3. 商談の進捗を管理(フェーズ管理)
  4. 成約したら「クローズ・ウィン」で終了


🛠 カスタマイズのポイント

  • オブジェクト追加:自社業務に合わせたデータ構造を作れる
  • ワークフロー/プロセスビルダー/フロー:業務自動化(通知、更新など)
  • レポートとダッシュボード:リアルタイムで成果を可視化
  • Lightning App Builder:画面レイアウトを自由に設計


☁️ 特徴とメリット

  • クラウドベースなのでインストール不要・リモート利用可
  • アップデートが自動(年3回)
  • ノーコードでも柔軟にカスタマイズ可能
  • AppExchangeで拡張アプリを導入可能


開発者公式ブログ

https://developer.salesforce.com/blogs/2020/10/step-up-your-lwc-skills-part-1

fukagawafukagawa

kebab-case を使う場面【主にHTML側】

1. コンポーネントのタグ名

LWCコンポーネントをHTML上で使うときは、必ず kebab-case で記述します

<my-custom-component></my-custom-component>

たとえApexクラスやJSファイル名が MyCustomComponent でも、HTMLでは my-custom-component と書きます。

2. カスタムデータ属性

data- 属性も kebab-case になります。

<div data-user-id="12345"></div>

3. CSSクラス名

クラス名も基本的に kebab-case で書くことが多いです(HTML/CSSの一般慣習に従うため)。

<template>
  <div class="profile-card-header">Hello</div>
</template>
fukagawafukagawa

prettierを適応させるためのコマンド

npm install -g prettier prettier-plugin-apex @prettier/plugin-xml\
fukagawafukagawa

文字数は200に設定しておくと見やすい
.prettierrcファイルの中に直接書く

{
  "trailingComma": "none",
  "plugins": ["prettier-plugin-apex", "@prettier/plugin-xml"],
  "overrides": [
    {
      "files": "**/lwc/**/*.html",
      "options": { "parser": "lwc" }
    },
    {
      "files": "*.{cmp,page,component}",
      "options": { "parser": "html" }
    }
  ],
  "printWidth": 200
}
fukagawafukagawa

ログ出力パターン

単一ログ

console.log("変数値", this.variable);
System.debug('変数値: ' + this.variable);

JSONパターン

console.log(JSON.stringify({ 変数値: this.variable }));
System.debug('[DEBUG] variableList: ' + JSON.serialize(variableList));

動いているかどうかの確認

console.log('[LOG] ファイル名 関数名 1');
fukagawafukagawa

開発者コンソール検証コード

開発者コンソールで Apex 実行(Execute Anonymous)時に必要なもの

1. 依存クラス・メソッドが存在していること

  • 使いたいクラスがすでに本番 or sandbox にデプロイ済みであること。
  • そのクラスのメソッドが public or global であること
  • DTO や DAO クラスがすべてコンパイル済み。

2. 検索条件クラスのインスタンスを生成する

  • new クラス名() で条件用クラスを生成し、必要な値を入れる。
className supplie = new className();
supplie.supplierName = 'テスト株式会社';

3. DAO(ロジック)を呼び出す

  • SOQLを生成するメソッドを呼ぶ。
DaoclassName dao = new DaoclassName();
String query = dao.getSalesOrderDetailQuery(supplie, Date.today(), false);

※ Date.today() のように日付をコード内で渡しているのは、SOQL内でバインド変数として利用するためです

4. クエリの実行と結果確認

List<SObject> records = Database.query(query);
System.debug('取得件数: ' + records.size());
fukagawafukagawa

Apexの検索条件クラスとはどのようなものか

下記のようなクラスがそれにあたる。

※データ転送オブジェクト(DTO)と混同しないように気を付けること

global class SearchFilterItem {
    @AuraEnabled
    public String fieldA { get; set; }
    @AuraEnabled
    public String fieldB { get; set; }
    @AuraEnabled
    public String fieldC { get; set; }

    // コンストラクタはグローバルで初期化値を空文字にする
    global SearchFilterItem() {
        fieldA = '';
        fieldB = '';
        fieldC = '';
    }
}

下記のコードのメリットは以下の通り。

  • fieldA / fieldBfieldC など、明確に「検索条件」に該当するフィールドが多数ある
  • 初期値が用意されており、検索フォームの「絞り込み条件」として使用するのにピッタリな構造
  • データの移動ではなく、「どんな条件で検索するか」を保持する用途がメインとして使える
fukagawafukagawa

LWCのeventの受け取り方の違い

event.target.value

  • HTML標準の<input><selectなど>で使用する
  • target はイベントが発生したDOM要素。ネイティブなUIコンポーネントはvalueプロパティを持っているため直接取れる。

event.detail.value

  • LWCなどで CustomEvent を使って値を渡している場合に使用する
  • CustomEventdetail プロパティに好きなデータを持たせられるので、値はそこに入っている。LWCではこれが推奨されている。
fukagawafukagawa

LWCのデコーダー一覧

Salesforce(特にLightning Web Components, LWC)における @api のような**デコレーター(decorators)**は、クラスのプロパティやメソッドに特別な意味を与えるために使われます。

デコレーター 用途
@api 親コンポーネントと子コンポーネント間でプロパティやメソッドを公開する。主に親から値を受け取る際に使用する
@track リアクティブな内部状態を定義する(現在は非推奨に近く、普通は this.property = ... のように普通のプロパティでもリアクティブに働く)。
@wire Salesforce のデータ(Apex や LDS)との連携を行う。自動的にデータを取得・更新するために使用。
@readonly 読み取り専用のプロパティを示す(※正式なLWC APIには含まれないが、Auraでは存在していた)。一般的には使わない。
fukagawafukagawa

Apex のアノテーション一覧

アノテーション 説明
@AuraEnabled LWCやAuraからApexメソッドやプロパティを使えるようにする。
@AuraEnabled(cacheable=true) クライアント側でキャッシュ可能なApexメソッドとして公開する(主に @wire 用)。
@InvocableMethod フローやプロセスビルダーで呼び出せるようにする。
@future 非同期処理を実行する。
@isTest テストクラス・メソッドを示す。
@testSetup テストデータセットアップ用のメソッドに使う。
fukagawafukagawa

LWCの初期化処理について

ライフサイクル名 いつ呼ばれるか
constructor() コンポーネントの作成時
connectedCallback() 要素がドキュメントに挿入されるとき
renderedCallback() コンポーネントを表示するとき
disconnectedCallback() 要素が削除されたとき
errorCallback() 下位コンポーネントでエラーが起きたとき

通常の初期化処理
とりあえずで確認したい場合はここに書いてみる

connectedCallback() {

}
fukagawafukagawa

標準コンポーネント(lightning-* コンポーネント)

📋 基本UIコンポーネント

コンポーネント 説明
lightning-button 通常のボタン
lightning-button-icon アイコン付きボタン
lightning-input テキスト/数値/メール等の入力欄
lightning-textarea 複数行入力
lightning-checkbox チェックボックス
lightning-radio-group ラジオボタン
lightning-combobox ドロップダウン
lightning-slider スライダー入力
lightning-toggle トグルスイッチ

🧩 データ表示系

コンポーネント 説明
lightning-card カード型UI
lightning-datatable テーブル
lightning-formatted-text 書式付きテキスト
lightning-formatted-number 書式付き数値
lightning-badge バッジ(ラベル)
lightning-pill タグのような要素
lightning-progress-bar 進捗バー
lightning-spinner 読み込み中のスピナー

📅 日付・時間

コンポーネント 説明
lightning-datepicker 日付入力
lightning-timepicker 時間入力

📦 ナビゲーション・レイアウト

コンポーネント 説明
lightning-tabset タブUI
lightning-accordion アコーディオンUI
lightning-layout レイアウト制御
lightning-tree ツリー構造
lightning-breadcrumb パンくずリスト

🔒 認証・セキュリティ系

コンポーネント 説明
lightning-record-edit-form 標準オブジェクトの編集フォーム
lightning-record-view-form 標準オブジェクトの表示フォーム
lightning-input-field record-edit-form 内で使うフィールド

📁 ファイル関連

コンポーネント 説明
lightning-file-upload ファイルアップロード
lightning-avatar ユーザーやレコードの画像表示

🔧 システム・ユーティリティ

コンポーネント 説明
lightning-navigation ページ遷移用のユーティリティ
lightning-toast トースト通知(JSで呼び出し)
lightning-modal モーダルウィンドウ(v58以降)

https://developer.salesforce.com/docs/component-library/bundle/lightning-input/documentation

fukagawafukagawa

[NoErrorObjectAvailable] Script error.

https://salesforce.stackexchange.com/questions/343576/noerrorobjectavailable-script-error

親コンポーネント

<template>
    <div onchildnotification={ghostMethod}>
        <div onchildnotification={handleChildNotification}>
            <lightning-textarea value="Parent Component"></lightning-textarea>
            <c-child-comp></c-child-comp>
        </div>
    </div>
</template>
import { LightningElement } from 'lwc';

export default class ParentComp extends LightningElement {
    handleChildNotification() {
        console.log('Child Event arrived');
    }
}

子コンポーネント

<template>
    <lightning-button label="Notify Parent Comp" onclick={notifyParent}></lightning-button>
</template>
import { LightningElement } from 'lwc';

export default class ChildComp extends LightningElement {
    notifyParent() {
        const event = new CustomEvent('childnotification', { bubbles: true });
        this.dispatchEvent(event);
    }
}

notifyParentメソッドがonclickで呼ばれる

childnotificationイベントを送信するparentComp

問題点

このコードには、親コンポーネントでイベントが正しくハンドリングされていないという問題がある。

具体的には、handleChildNotification は一番内側の<div>に設定されているけど、その<div>にイベントが届かない可能性が高い。

問題の原因

親テンプレート内のこの部分:

<div onchildnotification={ghostMethod}>
    <div onchildnotification={handleChildNotification}>
        <lightning-textarea value="Parent Component"></lightning-textarea>
        <c-child-comp></c-child-comp>
    </div>
</div>

<c-child-comp>からbubbles: true でイベントを送信しているが、そのイベントはLWCのシャドウDOMによって制限されるため、親コンポーネントの<div>には伝達しない。

WC では、カスタムイベントがシャドウDOMの外に出ないという制約があるため、bubbles: true だけでは親コンポーネントのテンプレート上でイベントを捕捉できない。

解決策

composed: true を設定する

const event = new CustomEvent('childnotification', { bubbles: true, composed: true });

composed: true を加えることで、シャドウDOM の外にイベントが出るようになる。

fukagawafukagawa

ESLintでエラー表示をかき消す

デプロイができていて、プログラム的にも何も問題がないのに、なぜかエラー表示される場合、以下のコメントを記入することによって表示を消すことができる。

    /* eslint-disable no-await-in-loop */

    /* eslint-enable no-await-in-loop */
fukagawafukagawa

nullチェックして代入する書き方

これがnullのときに変数aの値を入れる

const userid = event.target.value;

↓↓こんな感じになる

const userid = event.target.value ?? a;

null または undefined のときに判定される

const userid = event.target.value ? event.target.value : a;

空文字・0 を考慮したいときはこんな感じに書く

  • event.target.valuetruthy(真っぽい値) なら → それを userid に代入
  • そうでなければ(falsy なら) → a の値を代入
fukagawafukagawa

現在ログインしているユーザー名を取得

Apex側の処理

  /**
   * 現在ログインしているユーザー名
   */
  @AuraEnabled(cacheable=true)
  public static User getCurrentUser() {
    return [SELECT Id, Name, Email FROM User WHERE Id = :UserInfo.getUserId()];
  }

LWC側の処理

import getCurrentUser from "@salesforce/apex/Apexクラス名.getCurrentUser";

  @wire(getCurrentUser)
  wiredUser({ error, data }) {
    if (data) {
      this.currentUser = data;
      console.log("ユーザー名:", this.currentUser.Name);
    } else if (error) {
      console.error(error);
    }
  }

fukagawafukagawa

現在ログインしているユーザーIDを取得

Apex側の処理

Id currentUserId = UserInfo.getUserId();
System.debug('ユーザーID: ' + currentUserId);

LWC側の処理

import USER_ID from '@salesforce/user/Id';
console.log('ログインユーザーID:', this.userId);
fukagawafukagawa

JavaScriptのスプレット構文の書き方

return { ...existingData, updatedProperty: newValue };
  • ...existingData

    • existingData というオブジェクトのすべてのプロパティをコピーします。
  • updatedProperty: newValue

    • 新たに updatedProperty というプロパティを追加・上書きします。その値は newValue 変数の値です。
fukagawafukagawa

親と子の決まり方

Salesforceのコンポーネント構造(特にLightning Web ComponentsやAura Components)における「親コンポーネント」と「子コンポーネント」の関係は、**コンポーネントの入れ子構造(階層構造)**によって決まります。

親コンポーネント・子コンポーネントの決まり方

1. 親コンポーネント

  • あるコンポーネントの中で、他のコンポーネントをタグとして呼び出している側が親コンポーネントです。
  • 例: c-child-component<c-parent-component> のテンプレート内で使っている場合、c-parent-component が親で、c-child-component が子。

2. 子コンポーネント

  • 親コンポーネントのテンプレート内にタグとして埋め込まれているコンポーネント。
  • 子は親からプロパティを受け取ったり(@apiで公開されたプロパティ)、イベントを親に発火して通知する役割を持ちます。

具体例(LWCの場合)

親コンポーネント(parentComponent.html)

<template>
  <c-child-component message="こんにちは"></c-child-component>
</template>

子コンポーネント(childComponent.js)

import { LightningElement, api } from 'lwc';

export default class ChildComponent extends LightningElement {
  @api message;  // 親から受け取るプロパティ
}

ポイントまとめ

  • 親は子をテンプレート内で呼び出す
  • 子は親から@apiで公開された値を受け取る
  • 子はイベントを親に送って双方向コミュニケーションができる
  • 呼び出し階層で「呼び出す側」が親、「呼ばれる側」が子になる
fukagawafukagawa

ページネーションの基本的な考え方

✅ ページネーションとは?

大量のデータを「1ページに◯件だけ」表示し、ページを切り替えながら閲覧できるようにする機能。

用語 意味
pageSize 1ページあたりに表示するデータ件数(例:10件)
pageNumber 現在のページ番号(例:1ページ目 → 1)
offset 先頭から何件目から表示するか((pageNumber - 1) * pageSize
totalCount 該当するデータの総件数(全ページ数を知るために必要)
totalPages Math.ceil(totalCount / pageSize) で求められる、全体のページ数


全体像(構成)

  1. データ取得メソッド(Apex)
    • LIMITOFFSET を使って、指定のページ分だけ取得する。
  2. 総件数取得メソッド(Apex)
    • SELECT COUNT() で対象データの件数を返す。
  3. LWCでの状態管理
    • 現在のページ番号(this.currentPage
    • 1ページの表示件数(this.pageSize
    • 全ページ数(this.totalPages)を計算
  4. ページ移動UI
    • 「次へ」「前へ」「1 2 3 ...」などのボタンを用意し、currentPage を更新して再取得。


✅ LWC + Apex の場合(サーバーサイド)

public with sharing class AccountPaginationController {
    @AuraEnabled(cacheable=true)
    public static List<Account> getAccounts(Integer pageSize, Integer pageNumber) {
        Integer offsetSize = (pageNumber - 1) * pageSize;
        return [
            SELECT Id, Name
            FROM Account
            ORDER BY Name
            LIMIT :pageSize OFFSET :offsetSize
        ];
    }

    @AuraEnabled(cacheable=true)
    public static Integer getTotalCount() {
        return [SELECT count() FROM Account];
    }
}
import { LightningElement, track } from 'lwc';
import getAccounts from '@salesforce/apex/AccountPaginationController.getAccounts';
import getTotalCount from '@salesforce/apex/AccountPaginationController.getTotalCount';

export default class PaginationSample extends LightningElement {
    @track accounts = [];
    @track currentPage = 1;
    pageSize = 10;
    totalRecords = 0;
    totalPages = 0;

    connectedCallback() {
        this.loadData();
    }

    loadData() {
        getTotalCount()
            .then(count => {
                this.totalRecords = count;
                this.totalPages = Math.ceil(count / this.pageSize);
                this.fetchAccounts();
            });
    }

    fetchAccounts() {
        getAccounts({ pageSize: this.pageSize, pageNumber: this.currentPage })
            .then(result => {
                this.accounts = result;
            });
    }

    handleNext() {
        if (this.currentPage < this.totalPages) {
            this.currentPage++;
            this.fetchAccounts();
        }
    }

    handlePrev() {
        if (this.currentPage > 1) {
            this.currentPage--;
            this.fetchAccounts();
        }
    }
}
<template>
    <template if:true={accounts}>
        <template for:each={accounts} for:item="acc">
            <p key={acc.Id}>{acc.Name}</p>
        </template>
    </template>

    <div>
        <button onclick={handlePrev} disabled={currentPage <= 1}>Previous</button>
        <span>Page {currentPage} of {totalPages}</span>
        <button onclick={handleNext} disabled={currentPage >= totalPages}>Next</button>
    </div>
</template>
fukagawafukagawa

MVC+S+DAOの責務メモ

それぞれの役割

役割 主な処理内容 SOQL/DMLの位置づけ
View UI層 LWCやAuraなど なし
Controller 入出力処理 LWCからのリクエストを受けてServiceを呼ぶ なし
Service ビジネスロジック 処理の流れを記述(条件分岐・ルール判断など) 原則なし(DAOに委譲)
DAO データアクセス専用 SOQLやDMLを担当、オブジェクト単位でまとめる ここに集約
Model データの定義 SObjectやドメインクラス 定義のみ(SELECTはしない)

どこに何を書くのが正解なのか

処理内容 正しい場所 理由
単純なSELECT(1テーブル) DAO データアクセスの責任はDAOに一任するため
複雑なJOIN的処理(2テーブル以上) Service(がDAOを組み合わせて使う) ビジネスロジックに近いため
DML(Insert/Update/Delete) DAO 直接DBを操作する責任はDAOに集約
条件付き取得(業務判断あり) Service → DAO 条件の意味はService層で判断し、取得はDAOに任せる

まとめ

  • DAOがあるなら、SQOL/DMLはDAOに集約するのが正解
  • Serviceはあくまで「業務フローの司令塔」
  • Controllerはできるだけ「痩せた中継役」して、テストや保守性を高める。
fukagawafukagawa

Apex CPU time limit exceeded とは?

検索結果の上限を超えています。検索条件を変更ください。Apex CPU time limit exceededApex CPU time limit exceeded

Apex CPU time limit exceeded とは?

これは Apexコードの実行にかかった時間 が 制限(通常は同期処理で最大10,000ミリ秒 = 10秒)を超えた場合 にスローされるエラーです。

発生するタイミング

このエラーは、Apexコードが処理中にSalesforceのガバナ制限(Governor Limits)に引っかかった場合に、Apexの実行中に出ます。

フェーズ 発生可能性 説明
LWC → Apex 呼び出し時 この時点では出ません。
Apex メソッド内部 ここでロジックが複雑・大量データを扱っていると発生します。
SOQL ループ・for文などでデータ処理中 ループの中で計算・SOQL・DMLなどが多いとタイムオーバーになります。
バッチ処理中 ✅(別上限) バッチApexなどでは上限が60秒と緩和されますが、やはり出ます。

よくある原因

  • 大量のレコードを処理(SOQL結果が多い)
  • ネストされたループ(ループ内でループやSOQL)
  • 複雑なデータ構造の構築
  • TriggerやHelperメソッドが多重に動いている
  • 意図しない再帰呼び出し

対処方法の例

  1. SOQLやDMLをループ外に出す
  2. ループを減らす、ロジックを単純化
  3. 処理対象を絞る(検索条件を厳しくする)
  4. 処理を非同期化する(Queueable, Batch, @futureなど)
  5. Map, Setを活用して効率化
fukagawafukagawa

コンポーネント間通信について

親から子への通信

基本的にはパブリックプロパティで行う

親コンポーネント

<!-- ↓子コンポーネントのパブリックプロパティに値を渡す。 -->
<c-child name-value={name}></c-child>
// JS側で名前を設定
name = 'Taro';

子コンポーネント

 <!-- 親から渡された値を使用して、名前を出力。 -->
<div class="sample" style={backgroundStyle}>
    <span>Child: {nameValue}</span>
</div>
// @apiをつけることで親コンポーネントからアクセス可能。
import { LightningElement, api } from 'lwc';

export default class Child extends LightningElement {
    @api nameValue;
}

子から親への通信

この通信では、カスタムイベントを使用する。

子コンポーネント

<!-- 子要素がクリックされたときに handleClick を実行 -->
<a onclick={handleClick}>
    <div class="sample">
        <span>{itemLabel}</span>
    </div>
</a>
import { LightningElement, api } from 'lwc';

export default class Child extends LightningElement {
    @api itemLabel;

    handleClick() {
        const itemSelectedEvent = new CustomEvent('itemselect', {
            detail: this.itemLabel
        });
        this.dispatchEvent(itemSelectedEvent);
    }
}

さらに親の親に伝藩させるには以下のように記述する

const customEvent = new CustomEvent('itemselect', {
    detail: this.itemLabel,
    bubbles: true,     // 親へバブル
    composed: true     // シャドウDOMを超えて伝播
});
this.dispatchEvent(customEvent);

親コンポーネント

<!-- 子コンポーネントからのイベント「itemselect」をハンドリング -->
<c-child
    item-label="Item A"
    onitemselect={handleItemSelect}
    class="slds-m-horizontal_small">
</c-child>

<c-child
    item-label="Item B"
    onitemselect={handleItemSelect}
    class="slds-m-horizontal_small">
</c-child>

import { LightningElement } from 'lwc';

export default class Parent extends LightningElement {
    selectedItem;

    handleItemSelect(event) {
        this.selectedItem = event.detail;
    }
}

fukagawafukagawa

“ソーストラッキング ON”によるデプロイエラー

下記のようなエラーが出力される場合

  • VS Code 設定 → 「Salesforce: Enable Source Tracking」を OFF。
    ※検索窓に salesforce source tracking と入れると見つかります。

  • 右クリック → SFDX: Deploy This Source to Org(Push/Pull ではなく Deploy/Retrieve を使う)

エラー原因

  1. Org 側に Source Tracking が無いのに、VS Code 側は Source Tracking 前提のコマンドを実行
    • 拡張機能は内部で push/pull 的な差分検出を挟むことがあり、Org が非対応だと差分=0扱いになり、結果として === Deployed Source\nNo results found が表示されがちです。
  2. デプロイ対象が 0 件と判断されていた
    • 右クリックした場所が packageDirectories 外(sfdx-project.json の "packageDirectories" に含まれない)
    • .forceignore によって無視されている
    • *-meta.xml だけを選んでいた/メタデータの実体でない
    • 未保存(保存しておらず差分が無い)
    • manifest(package.xml)が空 or マッチしない
  3. デフォルト org の取り違え
    • 想定と違う org に投げて差分が 0(+その org は非トラッキング)
fukagawafukagawa

テストデータが正しく作成されているか確認したい

System.assertNotEquals の構文:

System.assertNotEquals(expected, actual, [message]);
  • expected:期待する値
  • actual:実際の値
  • message(省略可能):アサートが失敗した場合に表示されるメッセージ

使用例:

1. 値が異なる場合にアサート:

System.assertNotEquals(5, 10, '5 と 10 は異なる');
  • 510 が異なるので、アサートが成功します。

2. 値が null でないかを確認:

System.assertNotEquals(null, 'Some Value', 'null ではない');
  • 'Some Value'null ではないので、アサートが成功します。

3. オブジェクトの比較:

Account acc = new Account(Name = 'Test Account');
insert acc;

System.assertNotEquals(null, acc, 'Accountが正常に作成された');
  • accnull でないことを確認しています。insert が成功すれば、accnull ではないので、アサートが成功します。