{"id":28819564,"url":"https://github.com/double-o-seven/stubr","last_synced_at":"2025-10-26T12:32:05.475Z","repository":{"id":57715593,"uuid":"210423418","full_name":"Double-O-Seven/stubr","owner":"Double-O-Seven","description":"A library for stubbing/faking data objects in unit tests for example","archived":false,"fork":false,"pushed_at":"2022-02-24T00:08:22.000Z","size":1369,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-18T20:06:32.376Z","etag":null,"topics":["java","kotlin","stubbing","stubs","testing","testing-tools","unit-test"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Double-O-Seven.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}},"created_at":"2019-09-23T18:20:38.000Z","updated_at":"2022-02-23T22:58:43.000Z","dependencies_parsed_at":"2022-09-03T08:20:45.009Z","dependency_job_id":null,"html_url":"https://github.com/Double-O-Seven/stubr","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/Double-O-Seven/stubr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Double-O-Seven%2Fstubr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Double-O-Seven%2Fstubr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Double-O-Seven%2Fstubr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Double-O-Seven%2Fstubr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Double-O-Seven","download_url":"https://codeload.github.com/Double-O-Seven/stubr/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Double-O-Seven%2Fstubr/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260625270,"owners_count":23038172,"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":["java","kotlin","stubbing","stubs","testing","testing-tools","unit-test"],"created_at":"2025-06-18T20:06:32.221Z","updated_at":"2025-10-26T12:32:05.466Z","avatar_url":"https://github.com/Double-O-Seven.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Actions Status](https://github.com/Double-O-Seven/stubr/workflows/Java%20CI/badge.svg)](https://github.com/Double-O-Seven/stubr/actions)\n[![Release Version](https://img.shields.io/maven-central/v/ch.leadrian.stubr/stubr-core.svg?label=release)](https://search.maven.org/search?q=g:ch.leadrian.stubr)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/ba08c6eccb7045c8a5fa6c9c90d3f5bf)](https://www.codacy.com/gh/Double-O-Seven/stubr?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=Double-O-Seven/stubr\u0026amp;utm_campaign=Badge_Grade)\n[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/ba08c6eccb7045c8a5fa6c9c90d3f5bf)](https://www.codacy.com/gh/Double-O-Seven/stubr?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=Double-O-Seven/stubr\u0026utm_campaign=Badge_Coverage)\n\n# stubr\n\nStubr is an implementation of the \"Object Mother\" pattern and is a small, extensible library for creating stubs or\nfixtures for test data in unit tests.\n\n## Basics\n\nThe basic concept is very simple: You build a stubber, using different stubbing strategies for different classes and\ntypes and then you request a specific instance for your desired type.\n\nFor example:\n\n```java\npublic class Fubar {\n\n        public final String foo;\n        public final int bar;\n        public final int fubar;\n        \n        public Foo(String foo, int bar, int fubar) {\n                this.foo = foo;\n                this.bar = bar;\n                this.fubar = fubar;\n        }\n}\n\n\nStubber stubber = Stubber.builder()\n        .stubWith(StubbingStrategies.constructor()) // Instantiate an object using a constructor\n        .stubWith(StubbingStrategies.constantValue(\"Foo\")) // Provide \"Foo\" when a String is required\n        .stubWith(StubbingStrategies.suppliedValue(int.class, (int sequenceNumber) -\u003e sequenceNumber)) // Provide a sequence value when an int is required\n        .build();\nString stringValue = stubber.stub(String.class); // Foo\nint intValue1 = stubber.stub(int.class); // 0\nint intValue2 = stubber.stub(int.class); // 1\nFubar fubar = stubber.stub(Fubar.class); // Fubar(foo = \"Foo\", bar = 2, fubar = 3)\n```\n\n## But why?\n\nStubr is an implementation of the \"Object Mother\" pattern and is designed to complement existing mocking framework like\nMockito or MockK. While those frameworks are often used to mock certain behaviour, Stubr was created to provide valid,\ncommonly unmocked, instances of data objects.\n\nSometimes in your test case, you will access various values of a data object. The accessed values may potentially be\nnon-null. This will leave you with the following options:\n\n* Manually set up the whole data object\n* You mock the data object and define the return values\n\nIn both cases you end up with a lot of boiler plate code, especially when you need to set up or mock data whose content\nis not actually relevant to the test case.\n\nA possible solution for the problem described above is Stubr. Stubr can instantiate valid data objects for you, using\nsuitable default or custom stubbing strategies.\n\nWhen using immutable data classes Stubr works especially well with Kotlin data classes which provide a `copy()` method.\nIt will instantiate a valid instance from which you can derive a copy where you set the relevant properties yourself.\nThe same applies when using `@Builder(toBuilder = true)` annotated Lombok data classes for example.\n\nIn the `samples` project you will also find an example where the test subject of a unit test is automatically\ninstantiated with all dependencies being mocked with Mockito.\n\n## Concepts\n\n### Stubbing strategies\n\nA `Stubber` is composed using different `StubbingStrategy`s. A `StubbingStrategy` may provide stub values for only a\nspecific type or it may provide a generic solution to provide stubs for suitable types.\n\nIt consist of two basic methods, that depend on each other\n\n* `boolean accepts(StubbingContext context, Type type)`\n* `Object stub(StubbingContext context, Type type)`\n\n`accept` determines whether a `StubbingStrategy` is applicable for the given type and context. The `StubbingContext`\nconsists of the calling `Stubber` as well as the `StubbingSite` which describes where the stub value was requested.\n\n`stub` implements the provision of the stub value, which might be a fixed value, might depend on the type or context or\nmight even be a random value.\n\nAny implementation of `stub` may assume that the given context and type are accepted, so double-checking the input is\nnot required.\n\nA custom implementation may be used as follows:\n\n```java\nStubbingStrategy myAmazingStrategy = new MyAmazingStrategy();\nStubber stubber = Stubber.builder()\n        .stubWith(myAmazingStrategy)\n        .build();\n```\n\nMultiple strategies might accept the same types and therefore conflict each other. The behaviour in this case is that\nthe `Stubber` will prioritize the `StubbingStrategy` that was added the last during the build of the stubber `Stubber`.\nThe rule is therefore that the most generic strategies should be added first, while the most specific strategies should\nbe added last.\n\nFor example:\n\n```java\nStubber stubber = Stubber.builder()\n        .stubWith(veryGenericStrategy) // Accepts int, float and Strings for example\n        .stubWith(verySpecificStrategy) // Accepts only int\n        .build();\n```\n\nIn the above example, the `veryGenericStrategy` accepts multiple types, while the `verySpecificStrategy` only\naccepts `int`s. The built `Stubber` will therefore use `verySpecificStrategy` to provide stub values for `int`s and\nuse `veryGenericStrategy` for other types.\n\nVarious `StubbingStrategy` implementations can be found in `ch.leadrian.stubr.core.strategy.StubbingStrategies`.\n\n### Stubbing sites\n\n`StubbingStrategy`s can use the calling `Stubber` themselves to instantiate stubs. An simple example for that is a\nstubbing strategy that instantiates a stub using a suitable constructor. This constructor however, might itself need\nparameter values which can be provided by the `Stubber`.\n\nA `StubbingSite` describes where exactly and under what circumstances a `StubbingStrategy` requests additional stub\nvalues from the calling `Stubber`. This information can then be used to provide different values of the same type for\ndifferent `StubbingSite`s. One might for example configure the `Stubber` to provide a `null` value when a method\nparameter is annotated with `@Nullable` and non-null value otherwise.\n\nVarious `StubbingSite` implementations can be found in `ch.leadrian.stubr.core.site.StubbingSites`.\n\n### Matchers\n\nA `StubbingStrategy` has one additional default method:\n\n```java\nStubbingStrategy when(Matcher\u003c? super Type\u003e typeMatcher)\n```\n\nThis method returns a new `StubbingStrategy` that uses the receiver (`this`) to stub values, but in addition only\naccepts a given context and type if the given `Matcher` matches both the context and type.\n\nIt is therefore possible to conditionally apply `StubbingStrategy`s, for example depending on the `StubbingSite` or the\ntype or both.\n\nA `Matcher\u003cT\u003e` is a generic functional interface that requires the following method to be implemented:\n\n```java\nboolean matches(StubbingContext context, T value)\n```\n\nSince `Matcher`s are generic, a matcher may be combined using logical _and_, _or_ and _not_ operations, and in addition\nmatcher might delegate to other matches in order to match for example directly the `StubbingSite`.\n\nVarious `Matcher` implementations can be found in `ch.leadrian.stubr.core.matcher.Matchers`.\n\n#### Example\n\nThe following example discribes a situation when a constructor is used to stub a value and one of its parameters is\nannotated with `@One`. In this case, the integer stub value passed to the constructor would always be 1.\n\n```java\n\nimport static ch.leadrian.stubr.core.strategy.StubbingStrategies.*;\nimport static ch.leadrian.stubr.core.matcher.Matchers.*;\n\nStubber.builder()\n    // ... more configuration\n    .stubWith(constantValue(1).when(site(constructor(annotatedWith(One.class))))\n    .build()\n```\n\n### Selector\n\nA `Selector\u003cT\u003e` is a generic functional interface that selects zero or one values from a given list of values:\n\n```java\nOptional\u003cT\u003e select(StubbingContext context, List\u003c? extends T\u003e values)\n```\n\nIn core implementations of `StubbingStrategy`s `Selector`s are used to select an enum constant, a constructor or a\nfactory method.\n\nVarious `Selector` implementations can be found in `ch.leadrian.stubr.core.selector.Selectors`.\n\n## Download\n\nFor Maven:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ech.leadrian.stubr\u003c/groupId\u003e\n  \u003cartifactId\u003estubr-core\u003c/artifactId\u003e\n  \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nFor Gradle (Groovy DSL):\n\n```groovy\nimplementation 'ch.leadrian.stubr:stubr-core:2.0.1'\n```\n\nFor Gradle (Kotlin DSL):\n\n```groovy\nimplementation(\"ch.leadrian.stubr:stubr-core:2.0.1\")\n```\n\n## 3rd party support\n\n### JUnit 5\n\nStubr also includes an extension for JUnit Jupiter that allows you to get stub values through parameter injection. The\nonly requirement is to extend your test with the extension `ch.leadrian.stubr.junit.Stubr` and to annotated the desired\nmethod parameter with `ch.leadrian.stubr.junit.annotation.Stub`.\n\nIn addition, the tests might be configured using `ch.leadrian.stubr.junit.Include`, `ch.leadrian.stubr.junit.StubWith`\nand `ch.leadrian.stubr.junit.StubberBaseline`.\n\nFor example:\n\n```java\n@ExtendWith(Stubr.class)\n@StubWith(MyAmazingStubberProvider.class)\nclass MyAmazingTest {\n\n    @Test\n    void testSomething(@Stub String value) {\n        // test something\n    }\n\n}\n```\n\nThe JUnit 5 extension can be downloaded here:\n\nFor Maven:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ech.leadrian.stubr\u003c/groupId\u003e\n  \u003cartifactId\u003estubr-junit\u003c/artifactId\u003e\n  \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nFor Gradle (Groovy DSL):\n\n```groovy\nimplementation 'ch.leadrian.stubr:stubr-junit:2.0.1'\n```\n\nFor Gradle (Kotlin DSL):\n\n```groovy\nimplementation(\"ch.leadrian.stubr:stubr-junit:2.0.1\")\n```\n\n### Mockito\n\nStubr also includes a Mockito module that provides `StubbingStrategy` implementations that provide stubs using Mockito\nmocks. All non-void method call on such a mock will return a stub value provided by the `Stubber` that was used to mock\nthe stub.\n\nConcrete instances can be accessed through `ch.leadrian.stubr.mockito.MockitoStubbingStrategies`.\n\nA usage example:\n\n```java\nStubber stubber = Stubber.builder()\n    .stubWith(StubbingStrategies.constantValue(\"stubbed\"))\n    .stubWith(MockitoStubbingStrategies.mock())\n    .stubWith(MockitoStubbingStrategies.mock(MyMockedObject.class, mock -\u003e Mockito.when(mock.doSomething()).thenReturn(\"done\")))\n    .build();\nFoo someOtherMock = stubber.stub(Foo.class); // Stubbed using the generic mock stubbing strategy\nMyMockedObject obj = stubber.stub(MyMockedObject.class); // Stubbed using the specific mock stubbing strategy\nString result = obj.doSomething(); // result = \"done\"\n```\n\nThe Mockito extension can be downloaded here:\n\nFor Maven:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ech.leadrian.stubr\u003c/groupId\u003e\n  \u003cartifactId\u003estubr-mockito\u003c/artifactId\u003e\n  \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nFor Gradle (Groovy DSL):\n\n```groovy\nimplementation 'ch.leadrian.stubr:stubr-mockito:2.0.1'\n```\n\nFor Gradle (Kotlin DSL):\n\n```groovy\nimplementation(\"ch.leadrian.stubr:stubr-mockito:2.0.1\")\n```\n\n### Kotlin\n\nStubr also includes a Kotlin extension to simplify method calls and to stub Kotlin object classes.\n\n```kotlin\nobject MyObject {\n\n    fun doSomething() {\n    }\n\n}\n\ndata class MyData(val foo: String) {\n\n    constructor() : this(\"default-value\")\n\n}\n\nvar stubber = Stubber.builder()\n    .stubWith(StubbingStrategies.constantValue(\"stub-value\"))\n    .stubWith(KotlinStubbingStrategies.objectInstance())\n    .stubWith(KotlinStubbingStrategies.primaryConstructor())\n    .build()\nval myObject: MyObject = stubber.stub()\nval myData: MyData = stubber.stub() // MyData(foo = \"stub-value\"), instantiated with primary constructor\n```\n\nThe Kotlin extension can be downloaded here:\n\nFor Maven:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ech.leadrian.stubr\u003c/groupId\u003e\n  \u003cartifactId\u003estubr-kotlin\u003c/artifactId\u003e\n  \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nFor Gradle (Groovy DSL):\n\n```groovy\nimplementation 'ch.leadrian.stubr:stubr-kotlin:2.0.1'\n```\n\nFor Gradle (Kotlin DSL):\n\n```groovy\nimplementation(\"ch.leadrian.stubr:stubr-kotlin:2.0.1\")\n```\n\n### MockK\n\nStubr also includes a MockK module that provides `StubbingStrategy` implementations that provide stubs using MockK\nmocks. The provided stubs are by default relaxed MockK mocks.\n\nConcrete instances can be accessed through `ch.leadrian.stubr.mockk.MockKStubbingStrategies`.\n\nA usage example:\n\n```kotlin\nval stubber = Stubber.builder()\n    .stubWith(MockKStubbingStrategies.mockkAny())\n    .stubWith(MockKStubbingStrategies.mockk\u003cFoo\u003e {\n        every { getSomeValue() } returns \"Hello there!\"\n    })\n    .build();\nval foo = stubber.stub\u003cFoo\u003e() // Stubbed with the mockk() stubbing strategy\nval result = foo.getSomeValue() // result = \"Hello there!\"\nval bar = stubber.stub\u003cBar\u003e() // Stubbed with the mockkAny() stubbing strategy\nval otherResult = bar.getSomeOtherValue() // returns default value given by MockK\n```\n\nThe Mockito extension can be downloaded here:\n\nFor Maven:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ech.leadrian.stubr\u003c/groupId\u003e\n  \u003cartifactId\u003estubr-mockk\u003c/artifactId\u003e\n  \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nFor Gradle (Groovy DSL):\n\n```groovy\nimplementation 'ch.leadrian.stubr:stubr-mockk:2.0.1'\n```\n\nFor Gradle (Kotlin DSL):\n\n```groovy\nimplementation(\"ch.leadrian.stubr:stubr-mockk:2.0.1\")\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdouble-o-seven%2Fstubr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdouble-o-seven%2Fstubr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdouble-o-seven%2Fstubr/lists"}