{"id":29105186,"url":"https://github.com/dimpon/testprivate","last_synced_at":"2025-06-29T01:08:03.437Z","repository":{"id":57744334,"uuid":"224204642","full_name":"dimpon/testprivate","owner":"dimpon","description":"Library for testing private methods and fields","archived":false,"fork":false,"pushed_at":"2022-09-29T11:53:29.000Z","size":195,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-07-28T10:08:56.409Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/dimpon.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-11-26T13:56:52.000Z","updated_at":"2023-01-09T12:17:55.000Z","dependencies_parsed_at":"2022-08-30T10:51:37.322Z","dependency_job_id":null,"html_url":"https://github.com/dimpon/testprivate","commit_stats":null,"previous_names":[],"tags_count":18,"template":null,"template_full_name":null,"purl":"pkg:github/dimpon/testprivate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimpon%2Ftestprivate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimpon%2Ftestprivate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimpon%2Ftestprivate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimpon%2Ftestprivate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dimpon","download_url":"https://codeload.github.com/dimpon/testprivate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimpon%2Ftestprivate/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262518514,"owners_count":23323341,"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":[],"created_at":"2025-06-29T01:08:02.620Z","updated_at":"2025-06-29T01:08:03.414Z","avatar_url":"https://github.com/dimpon.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Maven Central](https://img.shields.io/maven-central/v/io.github.dimpon/testprivate.svg?label=maven%20central\u0026color=green)](https://search.maven.org/search?q=g:%22io.github.dimpon%22%20AND%20a:%22testprivate%22)\n[![GitHub Release](https://img.shields.io/github/release/dimpon/testprivate.svg?style=flat\u0026color=green)](https://github.com/dimpon/testprivate/releases)\n[![Build Status](https://travis-ci.com/dimpon/testprivate.svg?branch=master)](https://travis-ci.com/dimpon/testprivate)\n[![codecov](https://codecov.io/gh/dimpon/testprivate/branch/master/graph/badge.svg)](https://codecov.io/gh/dimpon/testprivate)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)\n[![javadoc](https://javadoc.io/badge2/io.github.dimpon/testprivate/javadoc.svg)](https://javadoc.io/doc/io.github.dimpon/testprivate)\n# Library for testing private methods/fields\n\nThat is not a secret that developers write Unit Tests for private methods. That is bad, an evidence that something wrong with design, and so on.\nBut we do it.\n\nFor instance, it is vitally important when you refactor legacy code, e.g. with ~1K lines of code classes and cover it with tests.\nThe really pure evil is changing access of tested method to package-private.\n  \nHere I offer an alternative solution. Maybe it will make your code cleaner. But better see the sample. \n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.dimpon\u003c/groupId\u003e\n    \u003cartifactId\u003etestprivate\u003c/artifactId\u003e\n    \u003cversion\u003e0.0.41\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n#### Assume that we have a class:\n```java\npublic class ObjectWithPrivates {\n    private final AtomicInteger count = new AtomicInteger(0);\n    private String name;\n\n    private String methodToTest(String in) {\n        return name + in + count.incrementAndGet();\n    }\n}\n```\n#### Unit Test:\n```java\ninterface TestPrivates {\n    void setName(String name);\n    String methodToTest(String in);\n    AtomicInteger getCount();\n}\n\n@Test\nvoid testPrivates() {\n    ObjectWithPrivates o = new ObjectWithPrivates();\n    TestPrivates testPrivates = API.lookupPrivatesIn(o).usingInterface(TestPrivates.class);\n\n    testPrivates.setName(\"Andromeda\");\n    String in = testPrivates.methodToTest(\"in\");\n    AtomicInteger count = testPrivates.getCount();\n\n    Assertions.assertEquals(\"Andromedain1\", in);\n    Assertions.assertEquals(1, count.get());\n}\n```\nAs you can see, we operate private fields and methods like if they were public. Fields of _o_ are changed.\n#### We also can do the same for statics:\n```java\npublic class ObjectWithPrivates {\n    private static AtomicInteger count = new AtomicInteger(0);\n    private static String name;\n\n    private static String methodToTest(String in) {\n        return name + in + count.incrementAndGet();\n    }\n}\n```\n#### Unit Test:\n```java\ninterface TestPrivates {\n    void setName(String name);\n    String methodToTest(String in);\n    AtomicInteger getCount();\n}\n\n@Test\nvoid testPrivates() {\n    TestPrivates testPrivates = API.lookupPrivatesIn(ObjectWithPrivates.class).usingInterface(TestPrivates.class);\n\n    testPrivates.setName(\"Andromeda\");\n    String in = testPrivates.methodToTest(\"in\");\n    AtomicInteger count = testPrivates.getCount();\n\n    Assertions.assertEquals(\"Andromedain1\", in);\n    Assertions.assertEquals(1, count.get());\n}\n```\n#### If a private field or method in superclass:\n```java\npublic class ObjectWithPrivates {\n    private  AtomicInteger count = new AtomicInteger(0);\n    private  String name;\n\n    private  String methodToTest(String in) {\n        return name + in + count.incrementAndGet();\n    }\n}\n\npublic class ObjectWithPrivatesSubclass extends ObjectWithPrivates {\n}\n```\nuse _lookupInSuperclass()_ method!\n#### Unit Test:\n```java\ninterface TestPrivates {\n    void setName(String name);\n    String methodToTest(String in);\n    AtomicInteger getCount();\n}\n\n@Test\nvoid testPrivates() {\n    ObjectWithPrivatesSubclass sub = new ObjectWithPrivatesSubclass();\n    TestPrivates testPrivates = API.lookupPrivatesIn(sub).lookupInSuperclass().usingInterface(TestPrivates.class);\n\n    testPrivates.setName(\"Andromeda\");\n    String in = testPrivates.methodToTest(\"in\");\n    AtomicInteger count = testPrivates.getCount();\n\n    Assertions.assertEquals(\"Andromedain1\", in);\n    Assertions.assertEquals(1, count.get());\n}\n```\n#### And cherry on the cake - creating objects using private constructors:\n```java\npublic class ClassC {\n    private ClassC(){...}\n    private ClassC(int a, String b, Object c, Long d) {...}\n}\n\n@Test\nvoid createObject() {\n    ClassC classC = API.createInstanceOf(ClassC.class).withArguments(new Integer(5), \"yo!\", new Long(123L), 15L);\n\n    Assertions.assertEquals(5, classC.getA());\n    Assertions.assertEquals(\"yo!\", classC.getB());\n    Assertions.assertEquals(123L, classC.getC());\n    Assertions.assertEquals(15L, classC.getD());\n}\n```\n#### And using private default constructor:\n```java\n@Test\nvoid createFromPrivateDefault() {\n    ClassD u = API.createInstanceOf(ClassD.class).usingDefaultConstructor();\n    Assertions.assertTrue(u instanceof ClassD);\n\n    Unsafe unsafe = API.createInstanceOf(Unsafe.class).usingDefaultConstructor();\n    Assertions.assertTrue(unsafe instanceof Unsafe);\n\n}\n```\nHope it can be useful. :)\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimpon%2Ftestprivate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdimpon%2Ftestprivate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimpon%2Ftestprivate/lists"}