{"id":14983002,"url":"https://github.com/codecentric/hikaku","last_synced_at":"2026-03-10T05:02:12.561Z","repository":{"id":34286822,"uuid":"167929609","full_name":"codecentric/hikaku","owner":"codecentric","description":"A library that tests if the implementation of a REST-API meets its specification.","archived":false,"fork":false,"pushed_at":"2023-11-28T15:53:45.000Z","size":799,"stargazers_count":199,"open_issues_count":19,"forks_count":19,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-20T03:07:49.139Z","etag":null,"topics":["cxf","dropwizard","hikaku","jax-rs","jersey","jersey2","micronaut","openapi","quarkus","raml","raml-test","rest","rest-api","restapi","resteasy","restful-api","restlet","spring","spring-mvc","wadl"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","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/codecentric.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":"2019-01-28T08:54:05.000Z","updated_at":"2025-02-16T07:42:43.000Z","dependencies_parsed_at":"2024-06-20T04:42:23.591Z","dependency_job_id":null,"html_url":"https://github.com/codecentric/hikaku","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/codecentric/hikaku","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fhikaku","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fhikaku/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fhikaku/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fhikaku/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codecentric","download_url":"https://codeload.github.com/codecentric/hikaku/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fhikaku/sbom","scorecard":{"id":296043,"data":{"date":"2025-08-11","repo":{"name":"github.com/codecentric/hikaku","commit":"b8a754f91b524b53a464167bf0abd6044caa25a4"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/19 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":"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":"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":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":"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":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: downloadThenRun not pinned by hash: install-jdk.sh:14","Info:   0 out of   1 downloadThenRun 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":"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE: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":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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 12 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-17T19:31:32.997Z","repository_id":34286822,"created_at":"2025-08-17T19:31:32.997Z","updated_at":"2025-08-17T19:31:32.997Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30325598,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T01:36:58.598Z","status":"online","status_checked_at":"2026-03-10T02:00:06.579Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cxf","dropwizard","hikaku","jax-rs","jersey","jersey2","micronaut","openapi","quarkus","raml","raml-test","rest","rest-api","restapi","resteasy","restful-api","restlet","spring","spring-mvc","wadl"],"created_at":"2024-09-24T14:06:33.807Z","updated_at":"2026-03-10T05:02:12.524Z","avatar_url":"https://github.com/codecentric.png","language":"Kotlin","readme":"# hikaku\n[![Build Status](https://api.travis-ci.org/codecentric/hikaku.svg?branch=master)](https://travis-ci.org/codecentric/hikaku) [![Maven Central Version](https://img.shields.io/maven-central/v/de.codecentric.hikaku/hikaku-core.svg)](https://search.maven.org/search?q=g:de.codecentric.hikaku)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/images/hikaku-logo-small.png\"\u003e\n\u003c/p\u003e\n\nHikaku (比較) is japanese and means \"comparison\". This library tests if a REST-API implementation meets its specification.\n\nIf you create your REST-API contract-first without using any type of generation, you have to make sure that specification and implementation don't diverge.\nThe aim of this project is to meet this need and offer a mechanism to check specification and implementation for equality without having to create requests which are fired against a mock server. So this library won't check the behavior of the API, but the structural correctness. Please see also the section [limitations](#limitations)\n\n## Currently supported\n\n+ **Specifications**\n  + [OpenAPI 3.0.X](openapi/README.md)\n  + [RAML 1.X](raml/README.md)\n  + [WADL](wadl/README.md)\n+ **Implementations**\n  + [Spring MVC 5.3.X](spring/README.md)\n  + [Micronaut](micronaut/README.md)\n  + [JAX-RS 3.0.X](jax-rs/README.md)\n    + [Apache CXF](http://cxf.apache.org)\n    + [Dropwizard](https://www.dropwizard.io)\n    + [Jersey](https://jersey.github.io)\n    + [Resteasy](https://resteasy.github.io)\n    + [Restlet](https://restlet.com/open-source/documentation/user-guide/2.3/extensions/jaxrs)\n    + [Quarkus](https://quarkus.io)\n  \nPlease refer to the list of [all features](docs/features.md). To check the feature support for each converter.\nIt is possible that not every converter supports every feature. Only the intersection of the features of two `EndpointConverter`s is used for the matching. Please keep that in mind regarding the equality of implementation and specification.\n  \n## Usage\n\nSetting up a test with hikaku is very simple. You just instantiate the `Hikaku` class and provide an `EndpointConverter` for the specification and another one for the implementation. Optionally, you can also pass an instance of `HikakuConfig`. Check the list of options and default values of the [config](docs/config.md). Then you call `match()` on the `Hikaku` class.\nThe match result is sent to one or multiple `Reporter`. If the test fails kotlin's `DefaultAsserter.fail()` method is called.\n\n### Example\n\nThere is an artifact for each converter. So we need one dependency for the specification and one for the implementation. In this example our project consists of an OpenAPI specification and a Spring implementation. The specification does not contain the _/error_ endpoints created by spring, so we want to omit those.\nFirst add the dependencies for the converters, that we want to use. In this case `hikaku-openapi` and `hikaku-spring`.\n\n```gradle\ndependencies {\n    testImplementation \"de.codecentric.hikaku:hikaku-openapi:$hikakuVersion\"\n    testImplementation \"de.codecentric.hikaku:hikaku-spring:$hikakuVersion\"\n}\n```\n\n#### Kotlin\n\nAnd now we can create the test case:\n\n```kotlin\n@SpringBootTest\nclass SpecificationTest {\n\n    @Autowired\n    private lateinit var springContext: ApplicationContext\n\n    @Test\n    fun `specification matches implementation`() {\n        Hikaku(\n                specification = OpenApiConverter(Paths.get(\"openapi.yaml\")),\n                implementation = SpringConverter(springContext),\n                config = HikakuConfig(\n                        filters = listOf(SpringConverter.IGNORE_ERROR_ENDPOINT)\n                )\n        )\n        .match()\n    }\n}\n```\n\n#### Java\n\nSame example in Java:\n\n```java\n@SpringBootTest\npublic class SpecificationTest {\n\n  @Autowired\n  private ApplicationContext springContext;\n\n  @Test\n  public void specification_matches_implementation() {\n    List\u003cFunction1\u003cEndpoint, Boolean\u003e\u003e filters = new ArrayList\u003c\u003e();\n    filters.add(SpringConverter.IGNORE_ERROR_ENDPOINT);\n\n    List\u003cReporter\u003e reporters = new ArrayList\u003c\u003e();\n    reporters.add(new CommandLineReporter());\n\n    new Hikaku(\n            new OpenApiConverter(Paths.get(\"openapi.json\")),\n            new SpringConverter(springContext),\n            new HikakuConfig(\n                    reporters,\n                    filters\n            )\n    )\n    .match();\n  }\n}\n```\n\n## Limitations\nHikaku checks the implementation with static code analysis. So everything that is highly dynamic is not covered by hikaku. There might be other libraries and frameworks that can cover these aspects by checking the behavior.\n\n### http status codes\nFor implementations the status codes are very dynamic. There are various ways to set a http status. For example using a `ResponseEntity` object in spring or using additional filters and so on. That's why hikaku does not support http status codes.\n\n### Request and response object\nFor implementations both request and response objects are highly dynamic. For response objects there might be a generic `ResponseEntity` as well or interfaces with different implementations can be used. In both cases (request and response) the objects can be altered by a serialization library and there a lot of different libs out there. That's why hikaku neither supports request nor response objects.\n\n## More Info\n\n* **Blog (english):** [Spotting mismatches between your spec and your REST-API with hikaku](https://blog.codecentric.de/en/2019/03/spot-mismatches-between-your-spec-and-your-rest-api/)\n* **Blog (german):** [ Abweichungen zwischen Spezifikation und REST-API mit hikaku erkennen](https://blog.codecentric.de/2019/03/abweichungen-zwischen-rest-api-spezifikation-erkennen/)\n* **Sample project** [A complete sample project](https://github.com/cc-jhr/hikaku-sample)\n","funding_links":[],"categories":["测试","Capabilities"],"sub_categories":["Testing"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodecentric%2Fhikaku","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodecentric%2Fhikaku","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodecentric%2Fhikaku/lists"}