# Declaring a Single Record with SBlueprint

The first step in assembling integration test data with ApexBlueprint is to declare a **blueprint for a single record** using `SBlueprint`. Instead of writing the procedural sequence "create an Account, set Industry to Technology, ...", you declare "what records I want to exist in the end" as a single expression.

This page walks through the five core methods of `SBlueprint` (`of` / `.set` / `.template` / `.alias` / `.use`) in order, plus `.after`, which declares ordering alone. APIs that handle multiple records — relationships (`withChildren`) and bulk generation (`times`) — are covered in [Relations, Bulk Generation, and Reference Patterns](/apex-stem/docs/apex-blueprint-relations-and-bulk).

## of(SObjectType): The Starting Point

Every `SBlueprint` declaration begins with this static method. It is the "first step" that tells the blueprint which SObject type you are about to assemble.

**Signature:** `SBlueprint.of(System.Type recordType)`

```apex
SBlueprint accountBp = SBlueprint.of(Account.class);
```

You then chain subsequent methods on the returned `SBlueprint` instance to stack values and relationships.

## .set(field, value): Setting a Field Value

The method you'll use most often. Declare a field name and value, one pair at a time.

**Signature:** `.set(String fieldName, Object value)`

```apex
SBlueprint accountBp = SBlueprint.of(Account.class)
    .set('Name', 'Test Account')
    .set('Industry', 'Technology')
    .set('AnnualRevenue', 1000000);
```

### Behavior Notes

- If you call `.set()` multiple times for the same field, **the last call wins**
- Values pre-set by `.template(...)` can be overridden by `.set(...)`. This forms the basis of the "shared defaults in template, only verification targets in `.set`" usage pattern
- Write only the fields that are the verification target of that specific test. Required fields, RecordTypeId, and other values common to all tests should be pushed into `.template(...)`

> The idea is to make "what does this test actually verify?" obvious from reading the `.set()` lines alone.

## .template(Map<String, Object>): Reusing Common Defaults

`.template(...)` applies a pre-defined Map of values all at once. By consolidating RecordTypeId, required fields, and other defaults you'd like to reuse across all tests, you keep the `.set(...)` calls in each test body to a minimum.

**Signature:** `.template(Map<String, Object> templateMap)`

### Best Practice: Consolidate Into a Single `Blueprints.cls`

For templates reusable across multiple tests, the canonical approach is to put them all in a **single `Blueprints.cls`, as one method per SObject** — named `{short SObject name}Basic()` (`accBasic()`, `oppBasic()`, and so on).

```apex
public with sharing class Blueprints {
    /** Base shape for a corporate account */
    public static Map<String, Object> accBasic() {
        return new Map<String, Object>{
            'Name' => 'TestAccount',
            'Industry' => 'Technology',
            'AnnualRevenue' => 500000
        };
    }

    /** Account variant: enterprise (an order of magnitude higher revenue) */
    public static Map<String, Object> accEnterprise() {
        return new Map<String, Object>{
            'Name' => 'EnterpriseAccount',
            'Industry' => 'Financial Services',
            'AnnualRevenue' => 10000000,
            'NumberOfEmployees' => 1000
        };
    }

    /** Base shape for an opportunity */
    public static Map<String, Object> oppBasic() {
        return new Map<String, Object>{
            'Name' => 'TestOpp',
            'StageName' => 'Prospecting',
            'CloseDate' => Date.today().addDays(30)
        };
    }
}
```

> **Why not one class per SObject?** Splitting them leaves each class as a thin wrapper that only returns a `Map`, scattered across many files. Keeping them together means **every base shape lives in one file**. When an admin adds a required field on the org and your integration tests all go red at once, the fix is obvious: add one line to the matching `xxxBasic()` map. Variants go in the same class with a prefix — `accEnterprise()`, `oppClosed()`.

Each test then pulls in the template and overrides only the field that is the verification target.

```apex
SBlueprint accountBp = SBlueprint.of(Account.class)
    .template(Blueprints.accBasic())
    .set('Name', 'Acme Trading Co');  // In this test, only Name is the main concern
```

> Values like RecordTypeId that are "common to all tests but cause failures if forgotten" should always live in the template to be safe.

## .alias(name): Attaching an Identifier

Attach a unique reference name (alias) to the blueprint. Aliases are used in two situations:

- Another blueprint references this one's value via `.use(alias, ...)`
- After `SOrchestrator.create()` runs, you retrieve the created record via `getByAlias(alias)`

**Signature:** `.alias(String aliasName)`

```apex
SBlueprint accountBp = SBlueprint.of(Account.class)
    .template(Blueprints.accBasic())
    .alias('parentAccount');
```

### Behavior Notes

- Aliases **must be unique** within the same `SOrchestrator`. Duplicates raise `Duplicate alias detected` at runtime
- Blueprints without an explicit `.alias(...)` get an auto-alias like `__Account_0_1__`, but retrieving these via `getByAlias` later is impractical. **If you plan to retrieve a record, always attach an explicit alias**
- Patterns that combine `.times(n)` with placeholder aliases like `'con_{#}'` are covered in [Relations, Bulk Generation, and Reference Patterns](/apex-stem/docs/apex-blueprint-relations-and-bulk)

## .use(alias, fromField, toField): Copying a Value from Another Blueprint

This is the most multi-purpose API in ApexBlueprint. In a single line, "copy a value held by another blueprint into one of my fields" expresses both **building a relationship** and **copying data**.

**Signature:** `.use(String aliasName, String fromField, String toField)`

- `aliasName`: The alias of the blueprint you want to reference (set via `.alias()`)
- `fromField`: The field to read from the source blueprint (e.g. `'Id'`, `'Industry'`)
- `toField`: The field to write to on this blueprint (e.g. `'AccountId'`, `'Description'`)

### Use Case 1: Building a Relationship (Id Copy)

The most common pattern. Link an `Opportunity` to an `Account`. `'parentAccount'` refers to the **identifier attached via `.alias('parentAccount')` on a separate Account blueprint**.

```apex
SBlueprint oppBp = SBlueprint.of(Opportunity.class)
    .set('Name', 'Test Opportunity')
    .set('StageName', 'Prospecting')
    .set('CloseDate', Date.today().addDays(30))
    .use('parentAccount', 'Id', 'AccountId');
```

`SOrchestrator` inserts `parentAccount` first to get its Id, then inserts the `Opportunity` — the order resolution is fully automatic. You don't write a single line of code to carry the parent Id around in a variable.

### Use Case 2: Copying Data (Other than Id)

`.use(...)` works on fields other than IDs too. It's handy for cases like "I want to copy the parent's Name into the child's description".

```apex
SBlueprint contactBp = SBlueprint.of(Contact.class)
    .set('LastName', 'TestContact')
    .use('parentAccount', 'Name', 'Description');
```

### Advanced Usage

Patterns like "link only some of the parents bulked with `{#}` to children" and "reference a grandparent (`{P0}` / `{P1}`)" are covered in detail in [Relations, Bulk Generation, and Reference Patterns](/apex-stem/docs/apex-blueprint-relations-and-bulk).

## .after(alias): Ordering Without a Value (v2.0.0+)

`.use()` decides the order **as a side effect of carrying a value**. `.after()` is that same method with the value copy taken out. It guarantees only that the referenced blueprint is inserted in an earlier layer, and touches no fields at all.

**Signature:** `.after(String aliasName)`

```apex
SBlueprint.of(Task.class)
    .set('Subject', 'Follow-up call')
    .after('baseOpportunity');   // inserted after baseOpportunity
```

Reach for it when **nothing links the records field-wise, but the insert order still matters**. Trigger side effects are the usual reason: "the roll-up comes out wrong unless the opportunity already exists when the activity lands" is a real situation in which no lookup connects the two records.

```apex
// ❌ Shoving an Id into a field you never read, purely to force an order
.use('baseOpportunity', 'Id', 'WhatId')

// ✅ If order is all you need, declare order
.after('baseOpportunity')
```

Placeholders such as `{#}` work exactly as they do in `.use()` (`.after('opp_{#}')`), and the `.after(alias, startAt, interval)` overload mirrors the same sequence controls.

> 📌 `.use()` and `.after()` become **edges in the same dependency graph** internally. The only difference is whether the edge carries a value; the ordering machinery is identical ([How Dependency Resolution Works](/apex-stem/docs/apex-blueprint-dependency-resolution-deep-dive)).

## Example: Combining Everything

Combine the five core methods above into a single test, and you get:

```apex
@isTest
static void testOppCreation() {
    SOrchestrator.start()
        .add(
            SBlueprint.of(Account.class)
                .template(Blueprints.accBasic())
                .alias('parentAccount')
        )
        .add(
            SBlueprint.of(Opportunity.class)
                .set('Name', 'Test Opportunity')
                .set('StageName', 'Prospecting')
                .set('CloseDate', Date.today().addDays(30))
                .use('parentAccount', 'Id', 'AccountId')
                .alias('targetOpp')
        )
        .create();

    // Verification
    Opportunity created = [
        SELECT Id, Name, AccountId FROM Opportunity WHERE Name = 'Test Opportunity' LIMIT 1
    ];
    Assert.isNotNull(created.AccountId);
}
```

Points:

- The `Account` side is **left to the template**. Since this test focuses on creating an Opportunity, the Account's contents just need to be valid — anything works
- The `Opportunity` side only `.set(...)`s **fields that are verification targets**. The intent that "this Opportunity ends up created and linked to an Account" reads directly from the code
- `SOrchestrator` resolves the dependencies, so you don't need to think about parent-child insertion order

> Since this page focuses on **declaring a single record**, the example writes two `SBlueprint`s into separate `.add(...)` calls and links them with `.use(...)`. In actual usage, however, when you have parent-child relationships, **`withChildren` lets you write the structure "Opportunity hanging under an Account" as a single blueprint, with the code's indentation hierarchy matching the data hierarchy and improving readability** — so that approach is preferred. See [Relations, Bulk Generation, and Reference Patterns](/apex-stem/docs/apex-blueprint-relations-and-bulk) for details.

## Related Documents

- [Resolving Dependencies and Executing DML with SOrchestrator](/apex-stem/docs/apex-blueprint-sorchestrator-guide): The execution phase that brings the assembled blueprints to life
- [Relations, Bulk Generation, and Reference Patterns](/apex-stem/docs/apex-blueprint-relations-and-bulk): Applications of `withChildren` / `times` / `{#}` / `{P0}` `{P1}`
- [API Reference: SBlueprint](/apex-stem/docs/apex-blueprint-api-sblueprint): Full method signatures
- [Back to the ApexBlueprint Guide](/apex-stem/docs/apex-blueprint-guide)
