{"id":16592606,"url":"https://github.com/unisay/moki","last_synced_at":"2025-09-11T13:13:53.880Z","repository":{"id":77363205,"uuid":"80535206","full_name":"Unisay/moki","owner":"Unisay","description":"Moki is a tool that provides and manages test services like mock http  server, database, FS folder, etc.","archived":false,"fork":false,"pushed_at":"2017-09-05T08:54:19.000Z","size":54,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-06T16:17:26.734Z","etag":null,"topics":["functional-programming","integration-testing","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Unisay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2017-01-31T15:52:57.000Z","updated_at":"2017-09-06T08:49:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"2eae133f-d788-434e-9c20-a95ece14aac3","html_url":"https://github.com/Unisay/moki","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Unisay/moki","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unisay%2Fmoki","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unisay%2Fmoki/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unisay%2Fmoki/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unisay%2Fmoki/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Unisay","download_url":"https://codeload.github.com/Unisay/moki/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unisay%2Fmoki/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274640941,"owners_count":25322845,"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","status":"online","status_checked_at":"2025-09-11T02:00:13.660Z","response_time":74,"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":["functional-programming","integration-testing","scala"],"created_at":"2024-10-11T23:21:31.230Z","updated_at":"2025-09-11T13:13:53.813Z","avatar_url":"https://github.com/Unisay.png","language":"Scala","readme":"Moki [![Build Status](https://travis-ci.org/Unisay/moki.svg?branch=master)](https://travis-ci.org/Unisay/moki)\n====\n### Purely functional black-box testing toolkit for Scala\n\nWikipedia defines [black-box testing](https://en.wikipedia.org/wiki/Black-box_testing) as:\n\n\u003e Black-box testing is a method of software testing that examines the functionality of an application without peering into its internal structures or workings. This method of test can be applied virtually to every level of software testing: unit, integration, system and acceptance. \n\nThe application (system) under test (further: [SUT](https://en.wikipedia.org/wiki/System_under_test)) rarely lives in isolation. Very often there are multiple external components that SUT depends upon: databases, file-systems, micro-services or any external OS processes (local or remote). Such dependencies together comprise an application environment that has to be up and running during tests. \n\nRelying on real production instances of SUT dependencies managed by 3-rd parties comes with a disadvantages:\n\n* External dependency might be still under development and not yet available (only its API contract).\n* Its not guaranteed that dependency is running each time a black box test is executed because it is controlled by other dev team;\n* Its hard to simulate failure modes using production systems\n    1. How would SUT behave if its dependency is being overloaded or shut down?\n    1. Simulating slow responses in order to test timeouts. \n* Its hard to test functionality that modifies external data without such modifications being observable by end-users.\n\nIn order to mitigate such drawbacks developer could use mocks that simulate relevant functions of real external dependencies. For example, its a common practice to use embedded databases (like HSQLDB and H2) instead of full-fledged DB servers, or mock servers like www.mock-server.com to simulate external REST services. One could also locally run a docker image of the dependency.\n \n Managing such dependencies can quickly become tedious and error-prone: Start before the test, make sure there are no TCP port conflicting, shut them down after test or in case of abrupt termination.\n \n Moki toolkit does exactly this: it defines a `TestService` monad and provides a way to compose many of them into an environment that is started before SUT and safely shut down after. It handles failures gracefully. Please consider the following scenario involving 3 test services - Database (\"DB\"), Micro-service providing REST API (\"API\") and Email server (\"Email\"):\n\n```\nStart DB (db port 5432)\n  Start EMAIL (email socket /var/sock/email)\n    Start API (exposed on URL http://localhost:12345)\n      Start SUT (depends on db port, email socket and API url, exposes http://localhost:8080)\n        Run test that uses SUT URL http://localhost:8080\n      Stop SUT\n    Stop API\n  Stop EMAIL\nStop DB\n```\n\nAny step can fail; its important that no test service is left running after test:\n\nSUT failed on start:\n```\nStart DB\n  Start EMAIL\n    Start API\n      Start SUT  ---\u003e Exception thrown during start\n        Run test \u003c--- Skipped\n      Stop SUT \u003c-- Skipped\n    Stop API \n  Stop EMAIL\nStop DB\n```\n\nTest service failed on start:\n```\nStart DB\n  Start EMAIL\n    Start API --\u003e Exception thrown\n  Stop EMAIL\nStop DB\n```\n\nTest service failed during shutdown:\n```\nStart DB\n  Start EMAIL\n    Start API\n      Start SUT\n        Run test\n      Stop SUT\n    Stop API \u003c--- throws Exception \n  Stop EMAIL \nStop DB\n```\n\nIn all this cases Moki guarantees that every test service is stopped and not abandoned.\n\n## Installation\n\n```\nresolvers += \"unisay-maven\" at \"https://dl.bintray.com/unisay/maven\"\nlibraryDependencies += \"com.github.unisay\" %% \"moki\" % \"5.1.0\" % \"test,it\"\n```\n## Usage\n\nMain concept is a `TestService[R]` that can be started and stopped; Type parameter `R` is a type of resource that is available to SUT while service is started. Examples are: URL, socket, TCP port, folder on FS.\n\nIts created like this:\n```scala\nval testService: TestService[Resource] = \n  TestService(start: Task[Resource], stop: Resource =\u003e Task[Unit])\n```\n\nMoki uses `fs2.Task` from [functional streams for scala](https://github.com/functional-streams-for-scala/fs2) to capture side-effectful computations.\n\n\nGiven 3 or more test services they can be composed like monads:\n```scala\nval serviceA: TestService[A] = ???\nval serviceB: A =\u003e TestService[B] = ???\nval serviceC: (A, B) =\u003e TestService[Unit] = ???\n\nval environment = for {\n  a \u003c- serviceA\n  b \u003c- serviceB(a)\n  _ \u003c- serviceC(a, b)\n} yield (a, b)\n\n// or with applicative syntax:\n\nval environment = (serviceA |@| serviceB |@| serviceC)((a: A, b: B, _) =\u003e (a, b))\n```\nThe environment, in turn, can run \"around\" the task that contains a test functionality like this:\n\n```scala\nval test: Task[Assertion] = environment run { case (a, b) =\u003e \n  // verify something using a and b\n  httpGetFrom(a) mustEqual readFileFrom(b)\n}\n\ntest.unsafeRun()\n```\n\nMoki runs it in the following order:\n\n```scala\n    a = serviceA.start\n      b = serviceB.start\n        serviceC.start\n          assertion = httpGetFrom(a) mustEqual readFileFrom(b)\n        serviceC.stop\n      serviceB.stop\n    serviceA.stop\n```\nreturning assertion to your test framework (ScalaTest or Specs2)\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2017\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funisay%2Fmoki","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funisay%2Fmoki","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funisay%2Fmoki/lists"}