{"id":36416994,"url":"https://github.com/ppi-ag/deep-sampler","last_synced_at":"2026-01-11T17:00:05.075Z","repository":{"id":37253710,"uuid":"313944687","full_name":"ppi-ag/deep-sampler","owner":"ppi-ag","description":"DeepSampler is a stubbing framework for compound tests","archived":false,"fork":false,"pushed_at":"2023-07-17T22:55:25.000Z","size":3915,"stargazers_count":11,"open_issues_count":23,"forks_count":2,"subscribers_count":5,"default_branch":"dev","last_synced_at":"2024-03-17T12:44:59.549Z","etag":null,"topics":["compound-test","integration-test","java","junit","mocking","mocking-framework","sampler","stub","stubbed-methods","stubbing","stubbing-framework","test-compound","testing"],"latest_commit_sha":null,"homepage":"https://ppi.de","language":"Java","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/ppi-ag.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-11-18T13:33:51.000Z","updated_at":"2024-02-01T10:43:22.000Z","dependencies_parsed_at":"2023-02-16T12:00:45.538Z","dependency_job_id":null,"html_url":"https://github.com/ppi-ag/deep-sampler","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/ppi-ag/deep-sampler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppi-ag%2Fdeep-sampler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppi-ag%2Fdeep-sampler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppi-ag%2Fdeep-sampler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppi-ag%2Fdeep-sampler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ppi-ag","download_url":"https://codeload.github.com/ppi-ag/deep-sampler/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppi-ag%2Fdeep-sampler/sbom","scorecard":{"id":742746,"data":{"date":"2025-08-11","repo":{"name":"github.com/ppi-ag/deep-sampler","commit":"fb2604859e574f6794007f1b95857710a225f412"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.7,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/7 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/gradle.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/ppi-ag/deep-sampler/gradle.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/ppi-ag/deep-sampler/gradle.yml/dev?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/gradle.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/ppi-ag/deep-sampler/gradle.yml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yaml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/ppi-ag/deep-sampler/publish.yaml/dev?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yaml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/ppi-ag/deep-sampler/publish.yaml/dev?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yaml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/ppi-ag/deep-sampler/publish.yaml/dev?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during GetBranch(main): error during branchesHandler.query: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 25 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T17:54:48.706Z","repository_id":37253710,"created_at":"2025-08-22T17:54:48.706Z","updated_at":"2025-08-22T17:54:48.706Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28314253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["compound-test","integration-test","java","junit","mocking","mocking-framework","sampler","stub","stubbed-methods","stubbing","stubbing-framework","test-compound","testing"],"created_at":"2026-01-11T17:00:04.255Z","updated_at":"2026-01-11T17:00:05.068Z","avatar_url":"https://github.com/ppi-ag.png","language":"Java","readme":"\u003cimg src=\"/docs/assets/logo.svg?raw=true\" alt=\"DeepSampler\" width=\"40%\"/\u003e\n\nVersion 2.1.0 - For older versions see [2.0.0](https://github.com/ppi-ag/deep-sampler/tree/%F0%9F%93%9A-maintenance-v2.0.0), [1.1.0](https://github.com/ppi-ag/deep-sampler/tree/%F0%9F%93%9A-maintenance-v1.1.0)\n\n![Build \u0026 Test](https://github.com/ppi-ag/deep-sampler/workflows/Build%20\u0026%20Test/badge.svg) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ppi-ag_deep-sampler\u0026metric=coverage)](https://sonarcloud.io/dashboard?id=ppi-ag_deep-sampler) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ppi-ag_deep-sampler\u0026metric=bugs)](https://sonarcloud.io/dashboard?id=ppi-ag_deep-sampler) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=ppi-ag_deep-sampler\u0026metric=code_smells)](https://sonarcloud.io/dashboard?id=ppi-ag_deep-sampler) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=ppi-ag_deep-sampler\u0026metric=sqale_rating)](https://sonarcloud.io/dashboard?id=ppi-ag_deep-sampler) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=ppi-ag_deep-sampler\u0026metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=ppi-ag_deep-sampler)\n\n# Build integration tests with JUnit and DeepSampler!\n\nDeepSampler is an advanced testing library designed for large software components that require high-quality testing. Unlike traditional unit-testing, DeepSampler's __component-testing__ approach enables you to test several integrated classes within a component, ensuring proper integration while isolating the component from the larger application. With its powerful __features__, DeepSampler simplifies the process of __injecting stubs__ into isolated components and 🎥 __recording 🧪 stub data__ at runtime from real-life examples. \n\nThis library is perfect for developers who need to ensure their software is of the highest quality and is well-suited for a wide range of applications. Give DeepSampler a try and take your testing to the next level!\n\nLet's say, we wanted to test a compound consisting of numerous classes and somewhere deep inside the compound is one class, a DAO, that reads \ndata from a Database:\n\n\u003cimg src=\"/docs/assets/deepsampler-demo-unsampled.png?raw=true\" alt=\"A DAO somewhere inside a compound reads data from a database\" width=\"50%\"/\u003e\n\nWe don't want to access the database during testing. So we mark the methods, that would access the db, as \"stubbed\" using DeepSampler. If we run the test with DeepSampler in recording-mode, every\ncall to the marked methods will be intercepted and all data, that was passed to it, or returned by it, is recorded. The recorded data, the __sample__, will be saved to \na JSON-file.\n\n\u003cimg src=\"/docs/assets/deepsampler-demo-recorder.png?raw=true\" alt=\"All calls to the DAO get intercepted and parameters and return values are recorded\" width=\"50%\"/\u003e\n\nAs a short appetizer, this is how we tell DeepSampler to attach a stub to the method `load()` in all instances of `MyDao`: \n```\n@PrepareSampler\nprivate MyDao myDaoSampler;\n...\nPersistentSample.of(myDaoSampler.load(Matchers.anyInt()));\n```\n\nIf we repeat the test with DeepSampler switched to player-mode, the marked method will not be called anymore. Instead, \na recorded sample from the JSON-file will be returned. \nIf the method is called with particular parameters, DeepSampler looks for a sample, that has been recorded with the same \nparameters.\n\n\u003cimg src=\"/docs/assets/deepsampler-demo-player.png?raw=true\" alt=\"Only samples from the previous recording are returned by the stub\" width=\"50%\"/\u003e\n\n# 🎓 Examples\nWe have a second repo where we collect runnable examples with detailed explanations: [DeepSampler Examples 🚀](https://github.com/ppi-ag/deep-sampler-examples).\n\n# Quickstart\nThe following tutorial demonstrates how to use DeepSampler with JUnit5 and Guice. \n\n## Installation\nWe use Maven to build the example. So, as a first step, we add the following dependencies to our pom.xml:\n\n```\n\u003cdependency\u003e\n   \u003cgroupId\u003ede.ppi\u003c/groupId\u003e\n   \u003cartifactId\u003edeepsampler-junit5\u003c/artifactId\u003e\n   \u003cversion\u003e2.1.0\u003c/version\u003e\n   \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n\n\u003cdependency\u003e\n   \u003cgroupId\u003ede.ppi\u003c/groupId\u003e\n   \u003cartifactId\u003edeepsampler-provider-guice\u003c/artifactId\u003e\n   \u003cversion\u003e2.1.0\u003c/version\u003e\n   \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n\n\u003cdependency\u003e\n   \u003cgroupId\u003ede.ppi\u003c/groupId\u003e\n   \u003cartifactId\u003edeepsampler-junit-json\u003c/artifactId\u003e\n   \u003cversion\u003e2.1.0\u003c/version\u003e\n   \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n## The Testee\nLet's say, we have a `GreetingService` that would create greeting messages for particular persons. We know only the ID \nof the person we want to greet, so the `GreetingService` needs to lookup the person somewhere (e.g., DB). \nThis is done by a \n`PersonService`, which provides a method `getName(personId)`. `getName()` in turn, would use a `PersonDAO` to \nload the `Person` from a Database.  \n\nNow we want to write a test for `GreetingService` and we want `PersonService` to be a part of the tested compound,\nso we cannot simply mock `PersonService`. Instead, we want to stub the `PersonDAO` in order to be independent of the\ndatabase. \n  \n## JUnit Test\nWe begin by setting up a JUnit Test. In general this will be an ordinary JUnit Test, but we use the \n`DeepSamplerExtension` to activate the DeepSampler environment:\n\n```\n@ExtendWith(DeepSamplerExtension.class)\nclass GreetingServiceTest {\n   ...\n}\n```\n\n 🔎 __Note__ `DeepSamplerExtension` basically provides annotations as a means of convenience for most common\nuse cases. However, DeepSampler can be used without this extension and even outside of JUnit Tests.\n(See [Define a Sampler by API](#define-a-sampler-by-api))\n\nThe actual stubbing is done by an aop-provider that uses - in this case - Guice aop. It is activated by passing\nthe `DeepSamplerModule` to guice. In real life we would most likely have a Guice module for the testee, and we would want\n to combine the testee's module with `DeepSamplerModule`, however for the sake of simplicity we use \n `DeepSamplerModule` directly for now, when we tell Guice to inject members into our test class: \n```\n@BeforeEach\nvoid injectWithGuice() {\n   Guice.createInjector(new DeepSamplerModule()).injectMembers(this);\n}\n```\n\n### Define a stub\nFirst we need a __Sampler__ which serves as a model, that describes which methods should be stubbed and what the\nstub should do. The Sampler is an instance of the class, that we want to stub. We define the Sampler by\nadding a property with the type of the stubbed class and add the annotation `PrepareSampler` to it:\n\n```\n@ExtendWith(DeepSamplerExtension.class)\nclass GreetingServiceTest {\n\n   @PrepareSampler\n   private PersonDao personDaoSampler;\n   ...\n}\n```\n\nInside a concrete test method we would now use the Sampler to define a stub:\n```\n@Test\nvoid greetingShouldBeGenerated() {\n   Sample.of(personDaoSampler.loadPerson(1)).is(new Person(\"Sarek\"));\n   ...\n}\n```\nThis means, the method `PersonDao::loadPerson` will be stubbed. If `loadPerson` is called with the parameter\n`1` the stub will return the __Sample__ `new Person(\"Sarek\")`. Otherwise, the original method will be called.\nThe stub applies to all instances of `PersonDAO`, no matter where the instances occur. \nIt will be active for the lifetime of the test method, so each test method can declare its own stubs. \n\nThat's it, we can now call the testee and check the results as usual:\n\n```\n@Test\nvoid greetingShouldBeGenerated() {\n   Sample.of(personDaoSampler.loadPerson(1)).is(new Person(\"Sarek\"));\n                                                    👇\n   assertEquals(\"Hello Sarek!\", greetingService.createGreeting(1));\n}\n```\n\n🔎 __Note__ Just to see that the stub is actually doing something, we could clear all stubs and repeat the\nassertion. Now the original method is used again, and we get another return value:\n\n```\nvoid greetingShouldBeGenerated() {\n   Sample.of(personDaoSampler.loadPerson(1)).is(new Person(\"Sarek\"));\n\n   assertEquals(\"Hello Sarek!\", greetingService.createGreeting(1));\n             👇\n   Sampler.clear();\n                          👇\n   assertEquals(\"Hello Geordi La Forge!\", greetingService.createGreeting(1));\n}\n```\n\n### Define a Sampler by API\nIf you want to use DeepSampler outside of JUnit or don't want to use the annotations, it is possible to create a Sampler\nusing the API:\n```\nPersonDao personDaoSampler = Sampler.prepare(PersonDao.class);\n```\n\n## SamplerFixtures\nUsually it will not be enough to write just one test for a particular compound like the `GreetingService`, so it\nwould be tedious to repeat the definition of stubs in each test case. To ease that, `SamplerFixtures` can be used to \ndefine reusable stubs. You can also think of a `SampleFixture` as a definition of a test compound, because the stubs\nwould isolate the compound from the environment in order to make it testable: \n```\npublic class GreetingServiceCompound implements SamplerFixture {\n   @PrepareSampler\n   private PersonDao personDaoSampler;\n\n   @Override\n   public void defineSamplers() {\n      Sample.of(personDaoSampler.loadPerson(Matchers.anyInt())).is(new Person(\"Sarek\"));\n   }\n}\n```\nOnce we have such a `SamplerFixture`, we can bind it to a test case using the annotation `@UseSamplerFixture` like so:\n```\n@Test\n@UseSamplerFixture(GreetingServiceCompound.class)\nvoid greetingShouldBeGenerated() {\n   ...\n}\n```\nThe stubs, that are defined by the `SamplerFixture`, are now active for the time the method runs. \n\n## Persistent Samples\nFor the sake of understandability, the tested compound in this example is fairly simple. However, DeepSampler was \nespecially designed for complex compound tests with quite a lot of stubs which also might return extensive Samples. \nIn these cases we would not want\nto have big sets of test data (Samples) in JUnit Test classes, we would rather separate test data from test logic. And\npossibly more important, we would not want to write such extensive Samples by hand. To ease this, DeepSampler \ncan save and load Samples from JSON-files.\n\n### Record a JSON-Sample\n\u003cimg src=\"/docs/assets/deepsampler-demo-recorder.png?raw=true\" alt=\"All calls to the DAO get intercepted and parameters and return values are recorded\" width=\"25%\" align=\"left\"/\u003e\n\nIn order to save Samples in a JSON-file, we __first__ need to define which methods should be stubbed and which methods should be recorded.\nThis is - again - done using `SamplerFixture`s. In contrast to the example above, we now need to define the Sampler slightly different:\n```\n     👇                                                              👇               👇\nPersistentSample.of(personDaoSampler.loadPerson(PersistentMatchers.anyRecordedInt()))   ;\n```\n\nPersistent Samples are defined using `PersistentSample` and we don't need to define a concrete Sample using `is()` anymore, since this value\nwill be provided by the JSON-File. Additionally, we can now use special parameter matchers for persistent samples. These new matchers honor the fact, that\nwe now want to match any parameters that have been recorded, instead of explicitlty hard-coded parameter values.\n__Second__ we need to tell DeepSampler to record all Data, that flows through the stubbed methods. This is simply done by adding the annotation\n`@SaveSamples` to the test method. \n\n```\n@Test\n@SaveSamples\n@UseSamplerFixture(GreetingServiceCompound.class)\nvoid recordSamplesToJson() {\n   greetingService.createGreeting(1);\n}\n```\nWhen we run this test, the stubs will call the original methods and additionally record the parameters and return values\nfor each call. The recorded data is then saved to a JSON-file.\n\nBy default `@SaveSamples` saves the JSON-file in a folder corresponding to the package of the current test case. The \nfilename is created using the class name, and the method name of the package. In this case we would get a file named\n`./de/ppi/deepsampler/examples/helloworld/GreetingServiceTest_recordSamplesToJson.json`.\n\n### Load a JSON-Sample\n\n\u003cimg src=\"/docs/assets/deepsampler-demo-player.png?raw=true\" alt=\"Only samples from the previous recording are returned by the stub\" width=\"25%\" align=\"left\"/\u003e\n\nFinally, we can use a `SamplerFixture`, and a JSON-file to build a test case. A JSON-file can be loaded using the \nannotation `@LoadSamples`: \n\n```\n@Test\n@LoadSamples\n@UseSamplerFixture(GreetingServiceCompound.class)\nvoid loadSamplesFromJson() {\n   assertEquals(\"Hello Sarek!\", greetingService.createGreeting(1));\n}\n```\nBy default `LoadSamples` searches for the JSON-file on the filesystem. The file name is created using the \nfull qualified class name, and the method name of the package. In this case DeepSampler would try to load a file named \n`./de/ppi/deepsampler/examples/helloworld/GreetingServiceTest_loadSamplesFromJson.json`.\n\n## Scopes\nDeepSampler is by default Thread-scoped. So Samples, that have been defined \nin one Thread, are available only in this particular Thread.\n\nYou can change the Scope using `Execution::setScope`. DeepSampler comes with two\npredefined Scopes:\n   * `ScopeType#THREAD`: Samples are Thread-exclusive, this is the default.\n   * `ScopeType#SINGLETON`: The same Samples are available across the entire VM and all Threads share the same Samples.\n  \n🔎 __Note__ the Scope must be changed before any Samples have been defined.\n\nThe following line would make all Samples available across all Threads:\n```\n    Execution.setScope(ScopeType.SINGLETON);\n```\n\n## Authoring custom persistence extensions\nThe format, in which samplers are recorded, is by default JSON. However, you can change the format by writing your own \npersistence-module. Let's say we wanted to create a persistence layer that is capable of writing YAML. Then we would \nhave to implement a model like this:\n```mermaid\n  graph TD;\n      A[\"MyTest#myTestMethod()\"]-- Annotated by --\u003eB[\"@SaveYamlSamples\"]\n      B-- Annotated by --\u003eC[\"@UseSourceManagerForSaving\"];\n      C-- creates --\u003eD[YamlSourceManagerFactory];\n      D-- configures --\u003eE[YamlSourceManager]\n      A-- records samples with --\u003eE;\n      E-- writes --\u003eF[\"sample.yaml\"];\n```\n   * `MyTest#myTestMethod()` is an example for a test-method that is supposed to record a sample-file in YAML-format \n      (or any other format, depending on your extension)\n   * `@SaveYamlSamples` is a custom annotation that is used as a command to tell DeepSampler, that samples should be \n      recorded. This annotation may be named freely, and it may have all kinds of properties, that can be used by the \n      custom extension to configure the recording.\n   * [@UseSourceManagerForSaving](deepsampler-junit/src/main/java/de/ppi/deepsampler/junit/UseSourceManagerForSaving.java) \n     is a meta-annotation that tells DeepSampler, that the annotated annotation is a command for saving samples.\n   * `YamlSourceManagerFactory` is referenced by `@UseSourceManagerForsaving` and it is used to create and configure a \n     `SourceManager`. It implements the interface \n     [SourceManagerFactory](deepsampler-junit/src/main/java/de/ppi/deepsampler/junit/SourceManagerFactory.java). \n     The configuration should be done using custom annotations. There is a convenience-method that is able to load \n     annotations from various places, like the test-method itself, or a `SamplerFixture`: \n     [JUnitSamplerUtils#loadAnnotationFromTestOrSamplerFixture](deepsampler-junit/src/main/java/de/ppi/deepsampler/junit/JUnitSamplerUtils.java#L158) \n   * `YamlSourceManager` is the class that is finally able to write the YAML-file. It implements the interface \n      [SourceManager](deepsampler-persistence/src/main/java/de/ppi/deepsampler/persistence/api/SourceManager.java). This \n      class is probably the most complex class to implement, since it needs to translate the \n      [ExecutionInformation](deepsampler-core/src/main/java/de/ppi/deepsampler/core/model/ExecutionInformation.java) to \n      a persistable format. `ExecutionInformation`s contain all data that is collected during the execution of stubbed methods.\n\nLoading samples is implemented very similar. The mentioned interfaces define methods for loading and saving samples. \nThe annotation, that commands DeepSampler to load samples, is marked by the meta annotation \n[@UseSourceManagerForLoading](deepsampler-junit/src/main/java/de/ppi/deepsampler/junit/UseSourceManagerForLoading.java)\n\nWe recommend placing the extension in two modules:\n   1. `persistence-module`: This module contains all code that is related to saving and loading samples independent of \n      JUnit. It should be possible to use the persistence without annotations or JUnit. \n      The [SourceManager](deepsampler-persistence/src/main/java/de/ppi/deepsampler/persistence/api/SourceManager.java)\n      -implementation and all it's utilities belong to this module.\n   2. `junit-configuration-modul`: A module that contains all code, that is necessary to use the `SourceManager` in \n      JUnit-tests together with annotation-based-configuration. The custom-annotations like `@SaveYamlSamples` and \n      the [SourceManagerFactory](deepsampler-junit/src/main/java/de/ppi/deepsampler/junit/SourceManagerFactory.java)\n      -implementation belong to this module.\n  \n\n# License\nDeepSampler is made available under the terms of the __MIT License__ (see [LICENSE.md](./LICENSE.md)).\n\nCopyright 2022 PPI AG (Hamburg, Germany)\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fppi-ag%2Fdeep-sampler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fppi-ag%2Fdeep-sampler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fppi-ag%2Fdeep-sampler/lists"}