{"id":16981795,"url":"https://github.com/cesarparra/test-data-framework","last_synced_at":"2026-01-05T07:05:53.852Z","repository":{"id":115969687,"uuid":"470745484","full_name":"cesarParra/test-data-framework","owner":"cesarParra","description":"The Salesforce Test Data Builder framework allows you to intuitively create Salesforce SObject data for your unit tests using a fluent language.  It provides base support for any SObject, standard or custom, out of the box, but allows you to adapt it to your custom needs.","archived":false,"fork":false,"pushed_at":"2022-04-15T12:55:45.000Z","size":8102,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-14T17:03:37.808Z","etag":null,"topics":["apex","framework","salesforce","salesforce-developers","salesforcedx","sfdx","testing","unit-testing"],"latest_commit_sha":null,"homepage":"https://github.com/cesarParra/test-data-framework","language":"Apex","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cesarParra.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-16T20:43:18.000Z","updated_at":"2025-01-07T12:47:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"f831954c-d2ac-4a80-a735-e27c38de5a3f","html_url":"https://github.com/cesarParra/test-data-framework","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesarParra%2Ftest-data-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesarParra%2Ftest-data-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesarParra%2Ftest-data-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesarParra%2Ftest-data-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cesarParra","download_url":"https://codeload.github.com/cesarParra/test-data-framework/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244885515,"owners_count":20526293,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apex","framework","salesforce","salesforce-developers","salesforcedx","sfdx","testing","unit-testing"],"created_at":"2024-10-14T02:06:29.518Z","updated_at":"2025-10-14T12:10:40.586Z","avatar_url":"https://github.com/cesarParra.png","language":"Apex","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eSalesforce Test Data Builder\u003c/h1\u003e\n  \u003cp\u003e\n    Easy and intuitive way to create Salesforce unit test data.\n  \u003c/p\u003e\n\n\u003ch4\u003e\n    \u003ca href=\"https://cesarparra.github.io/test-data-framework\"\u003eDocumentation\u003c/a\u003e\n  \u003cspan\u003e · \u003c/span\u003e\n    \u003ca href=\"https://github.com/cesarParra/test-data-framework/issues\"\u003eReport Bug\u003c/a\u003e\n  \u003cspan\u003e · \u003c/span\u003e\n    \u003ca href=\"https://github.com/cesarParra/test-data-framework/issues\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/h4\u003e\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n## 💡 About\n\nThe Salesforce Test Data Builder framework allows you to intuitively create Salesforce SObject data for your\nunit tests using a fluent language. \n\nIt provides base support for any SObject, standard or custom, out of the box, but allows you\nto adapt it to your custom needs.\n\n## 🏁 Getting Started\n\n### 🏃 Deploying\n\nTo deploy clone or download this repo and push the contents of `force-app/main/default/classes` to your org.\n\n### Usage\n\n#### Quick Start\n\nTip: See the `IntegrationTests` class for more in depth example usages of the framework.\n\nA record can be created through the following syntax\n\n```apex\nContact anyContact = (Contact)SObjectTestDataBuilder.of(Contact.SObjectType).registerNewForInsert();\nSObjectTestDataBuilder.commitRecords();\n```\n\n`SObjectTestDataBuilder.of` receives an `SObjectType` for the type of record that you want to create. Calling\n`registerNewForInsert` on the returned object will queue up the record for bulk insertion once \n`SObjectTestDataBuilder.commitRecords()` gets called.\n\nYou can also create multiple records by using the `registerNewForInsert` overload that takes the number\nof records to create\n\n```apex\nList\u003cContact\u003e multipleContacts = (List\u003cContact\u003e)SObjectTestDataBuilder.of(Contact.SObjectType).registerNewForInsert(5);\nSObjectTestDataBuilder.commitRecords();\n```\n\nBy default, the framework will try to resolve for any required fields on the SObject. In the `Contact` example,\nthe `LastName` field is a required text field, so the framework will use a `String` from the `DefaultTestData`\nclass to fill up that field.\n\nFeel free to modify that class to change the defaults for any of the different field types.\n\nDuring record creation you can also explicitly specify any field data you want to create by chaining `with` calls\nand passing an SObjectField and a value:\n\n```apex\nContact anyContact = (Contact)SObjectTestDataBuilder.of(Contact.SObjectType)\n        .with(Contact.FirstName, 'John')\n        .with(Contact.LastName, 'Smith')\n        .registerNewForInsert();\nSObjectTestDataBuilder.commitRecords();\n```\n\n#### Relationships\n\nWhen creating test data you might want to also create relationship records, either parent-to-child\nor child-to-parent, which are both supported by the framework.\n\nTo create a **parent-to-child** relationship you can use the `withChild` method:\n\n```apex\nAccount accountWithChild = (Account)SObjectTestDataBuilder.of(Account.SObjectType)\n        .withChild(\n                SObjectTestDataBuilder.of(Contact.SObjectType),\n                Contact.AccountId\n        )\n        .registerNewForInsert();\nSObjectTestDataBuilder.commitRecords();\n```\n\nThe `withChild` method takes 2 arguments: a builder for the child (which can be obtained by calling `SObjectTestDataBuilder.of`)\nand the relationship field between the 2 objects.\n\n**Retrieving child records**\n\nOnce the records have been inserted to the database (after the call to `SObjectTestDataBuilder.commitRecords()`) you do not\nneed to query the database to get the reference to the children. Instead, the framework keeps a reference of all inserted records\nso you can retrieve the children by using the `SObjectTestDataBuilder.getChildrenOfTypeById` method:\n\n```apex\nList\u003cContact\u003e accountChildren = SObjectTestDataBuilder.getChildrenOfTypeById(accountWithChild.Id, Contact.SObjectType);\n```\n\nTo create **child-to-parent** relationships the framework has the concept of \"late binding\", which is a way to specify\na relationship between objects without calling the database until necessary for bulkification purposes.\n\nThe late binding is used with the regular `with` method that is used to specify any field value. But instead\nof passing a record ID value (which *is* valid as well, but will not take advantage of bulkification) you pass\nin a `SObjectTestDataBuilder.LateBinding` object, which can be obtained by calling the `SObjectTestDataBuilder.lateBinding`\nmethod:\n\n```apex\nSObjectTestDataBuilder.of(OrderItem__c.SObjectType)\n                    .with(OrderItem__c.Order__c, SObjectTestDataBuilder.lateBinding(Order__c.SObjectType))\n                    .registerNewForInsert();\nSObjectTestDataBuilder.commitRecords();\n```\n\nThis will create both the `OrderItem__c` and the parent `Order__c`.\n\n#### Custom Builders\n\nWhen creating SObjects you will probably want more control over the data than what the default builder gives you. The framework\nalso allows you to create custom builders for different SObjectTypes.\n\nTo create a custom builder you will need to **both** extend `SObjectTestDataBuilder` and implement `ITestDataBuilder`.\nFor the framework to automatically detect your custom builder it also **needs* to have a name that ends in `TestDataBuilder` \n(though there is a way to explicitly specify the builder to the framework, explained below).\n\nAny custom builder should start with some boilerplate code that looks as follows:\n\n```apex\n@IsTest\npublic with sharing class OrderTestDataBuilder extends SObjectTestDataBuilder implements ITestDataBuilder {\n  public override SObjectType getSObjectType() {\n    return Order__c.SObjectType;\n  }\n\n  public OrderTestDataBuilder with(SObjectField field, Object value) {\n    return (OrderTestDataBuilder) withData(field, value);\n  }\n\n  public Order__c registerNewForInsert() {\n    return (Order__c) this.registerSObjectForInsert();\n  }\n\n  public List\u003cSObject\u003e registerNewForInsert(Integer numberOfRecords) {\n    return this.registerSObjectsForInsert(numberOfRecords);\n  }\n\n  public OrderTestDataBuilder withChild(ITestDataBuilder childBuilder, SObjectField relationshipField) {\n    return (OrderTestDataBuilder)this.withChildData(childBuilder, relationshipField);\n  }\n\n  protected override Map\u003cSObjectField, Object\u003e getDefaultValueMap() {\n    return new Map\u003cSObjectField, Object\u003e {\n            Order__c.Customer__c =\u003e bindTo(SObjectTestDataBuilder.of(Account.SObjectType))\n    };\n  }\n}\n```\n\nCreating a custom builder gives you the following functionality:\n* Allows you to create additional `withSomeField` method, which will make your code more fluent\n* You can optionally override the `getDefaultValueMap` method, which will allow you to create default data tailored to the SObject.\n  * Note by the example that you can use late binding by calling the `bindTo` method automatically provided to you when extending `SObjectTestDataBuilder`.\n* You can optionally override the `beforeInsert` and `afterInsert` methods, which will allow you to execute code before and after hitting the database for the insertion of your records.\n\n#### Default resolution vs. Explicitly specifying\n\nBy default, the framework will look for any class that ends with `TestDataBuilder` to try and automatically resolve with test data builder to use.\nWhen one is not found then the `DefaultTestDataBuilder` will be used, which will attempt to resolve required fields with default data. But you can also\nexplicitly specify which builder to use to the framework in the unit test itself, in case you want to either override the automatic resolution and use a different builder,\nor if you simply don't want to follow the naming convention.\n\nYou can do that by using the `SObjectTestDataBuilder.registerBuilder` method:\n\n```apex\nSObjectTestDataBuilder.registerBuilder(Order.SObjectType, CustomOrderBuilder.class);\n```\n\n### 🧪 Tests\n\nThis repo provides the `IntegrationTests` class with examples of all functionality provided by the framework. The\n`kitchenSinkExample` provides an example of a complex hierarchy of objects.\n\n## 🚧 Roadmap\n\n* [ ] Release as unmanaged package\n* [ ] In-memory support\n\n\n## 🤝Contributing\n\nContributions are always welcome!\n\n\n## ⚖️License\n\nDistributed under the MIT License. See LICENSE file for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcesarparra%2Ftest-data-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcesarparra%2Ftest-data-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcesarparra%2Ftest-data-framework/lists"}