{"id":16547016,"url":"https://github.com/stefanbirkner/system-lambda","last_synced_at":"2025-04-05T07:07:46.452Z","repository":{"id":45644825,"uuid":"53443371","full_name":"stefanbirkner/system-lambda","owner":"stefanbirkner","description":"System Lambda is a collection of functions for testing code that uses java.lang.System","archived":false,"fork":false,"pushed_at":"2024-04-08T01:09:24.000Z","size":448,"stargazers_count":216,"open_issues_count":16,"forks_count":15,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-29T06:08:18.560Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/stefanbirkner.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2016-03-08T20:36:00.000Z","updated_at":"2025-03-24T13:43:58.000Z","dependencies_parsed_at":"2024-11-09T19:01:30.915Z","dependency_job_id":"579b30c5-c513-4cc0-ace4-ec60c5ba9090","html_url":"https://github.com/stefanbirkner/system-lambda","commit_stats":{"total_commits":16,"total_committers":5,"mean_commits":3.2,"dds":0.25,"last_synced_commit":"18e1f1ed60d1b4346371cdf09ad21c172f438309"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanbirkner%2Fsystem-lambda","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanbirkner%2Fsystem-lambda/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanbirkner%2Fsystem-lambda/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanbirkner%2Fsystem-lambda/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stefanbirkner","download_url":"https://codeload.github.com/stefanbirkner/system-lambda/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247299833,"owners_count":20916190,"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":"2024-10-11T19:13:20.716Z","updated_at":"2025-04-05T07:07:46.431Z","avatar_url":"https://github.com/stefanbirkner.png","language":"Java","funding_links":[],"categories":["测试"],"sub_categories":[],"readme":"# System Lambda\n\n![Build Status Linux](https://github.com/stefanbirkner/system-lambda/workflows/Java%20CI%20with%20Maven/badge.svg?branch=master) [![Build Status Windows](https://ci.appveyor.com/api/projects/status/4ck6g0triwhvk9dy?svg=true)](https://ci.appveyor.com/project/stefanbirkner/system-lambda)\n\nSystem Lambda is a collection of functions for testing code which uses\n`java.lang.System`.\n\nSystem Lambda is published under the\n[MIT license](http://opensource.org/licenses/MIT). It requires at least Java 8.\n\nFor JUnit 4 there is an alternative to System Lambda. Its name is\n[System Rules](http://stefanbirkner.github.io/system-rules/index.html).\n\n## Installation\n\nSystem Lambda is available from\n[Maven Central](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.github.stefanbirkner%22%20AND%20a%3A%22system-lambda%22).\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.stefanbirkner\u003c/groupId\u003e\n    \u003cartifactId\u003esystem-lambda\u003c/artifactId\u003e\n    \u003cversion\u003e1.2.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nPlease don't forget to add the scope `test` if you're using System Lambda for\ntests only. The [changelog](CHANGELOG.md) lists all the changes of System\nLambda.\n\n\n## Usage\n\nImport System Lambda's functions by adding\n\n```java\nimport static com.github.stefanbirkner.systemlambda.SystemLambda.*;\n```\n\nto your tests.\n\n\n### System.exit\n\nCommand-line applications terminate by calling `System.exit` with some status\ncode. If you test such an application then the JVM that executes the test exits\nwhen the application under test calls `System.exit`. You can avoid this with\nthe method `catchSystemExit` which also returns the status code of the\n`System.exit` call.\n\n```java\n@Test\nvoid application_exits_with_status_42(\n) throws Exception {\n  int statusCode = catchSystemExit(() -\u003e {\n    System.exit(42);\n  });\n  assertEquals(42, statusCode);\n}\n```\n\nThe method `catchSystemExit` throws an `AssertionError` if the code under test\ndoes not call `System.exit`. Therefore your test fails with the failure message\n\"System.exit has not been called.\"\n\n\n### Environment Variables\n\nThe method `withEnvironmentVariable` allows you to set environment variables\nwithin your test code that are removed after your code under test is executed.\n\n```java\n@Test\nvoid execute_code_with_environment_variables(\n) throws Exception {\n  List\u003cString\u003e values = withEnvironmentVariable(\"first\", \"first value\")\n    .and(\"second\", \"second value\")\n    .execute(() -\u003e asList(\n      System.getenv(\"first\"),\n      System.getenv(\"second\")\n    ));\n  assertEquals(\n    asList(\"first value\", \"second value\"),\n    values\n  );\n}\n```\n\n\n### System Properties\n\nThe method `restoreSystemProperties` guarantees that after executing the test\ncode each System property has the same value like before. Therefore you can\nmodify System properties inside of the test code without having an impact on\nother tests.\n\n```java\n@Test\nvoid execute_code_that_manipulates_system_properties(\n) throws Exception {\n  restoreSystemProperties(() -\u003e {\n    System.setProperty(\"some.property\", \"some value\");\n    //code under test that reads properties (e.g. \"some.property\") or\n    //modifies them.\n  });\n\n  //Here the value of \"some.property\" is the same like before.\n  //E.g. it is not set.\n}\n```\n\n\n### System.out and System.err\n\nCommand-line applications usually write to the console. If you write such\napplications you need to test the output of these applications. The methods\n`tapSystemErr`, `tapSystemErrNormalized`, `tapSystemOut`,\n`tapSystemOutNormalized`, `tapSystemErrAndOut` and\n`tapSystemErrAndOutNormalized` allow you to tap the text that is written to\n`System.err`/`System.out`. The methods with the suffix `Normalized` normalize\nline breaks to `\\n` so that you can run tests with the same assertions on\ndifferent operating systems.\n\n```java\n@Test\nvoid application_writes_text_to_System_err(\n) throws Exception {\n  String text = tapSystemErr(() -\u003e {\n    System.err.print(\"some text\");\n  });\n  assertEquals(\"some text\", text);\n}\n\n@Test\nvoid application_writes_mutliple_lines_to_System_err(\n) throws Exception {\n  String text = tapSystemErrNormalized(() -\u003e {\n    System.err.println(\"first line\");\n    System.err.println(\"second line\");\n  });\n  assertEquals(\"first line\\nsecond line\\n\", text);\n}\n\n@Test\nvoid application_writes_text_to_System_out(\n) throws Exception {\n  String text = tapSystemOut(() -\u003e {\n    System.out.print(\"some text\");\n  });\n  assertEquals(\"some text\", text);\n}\n\n@Test\nvoid application_writes_mutliple_lines_to_System_out(\n) throws Exception {\n  String text = tapSystemOutNormalized(() -\u003e {\n    System.out.println(\"first line\");\n    System.out.println(\"second line\");\n  });\n  assertEquals(\"first line\\nsecond line\\n\", text);\n}\n\n@Test\nvoid application_writes_text_to_System_err_and_out(\n) throws Exception {\n  String text = tapSystemErrAndOut(() -\u003e {\n    System.err.print(\"text from err\");\n    System.out.print(\"text from out\");\n  });\n  assertEquals(\"text from errtext from out\", text);\n}\n\n@Test\nvoid application_writes_mutliple_lines_to_System_err_and_out(\n) throws Exception {\n  String text = tapSystemErrAndOutNormalized(() -\u003e {\n    System.err.println(\"text from err\");\n    System.out.println(\"text from out\");\n  });\n  assertEquals(\"text from err\\ntext from out\\n\", text);\n}\n```\n\nYou can assert that nothing is written to `System.err`/`System.out` by wrapping\ncode with the function\n`assertNothingWrittenToSystemErr`/`assertNothingWrittenToSystemOut`. E.g. the\nfollowing tests fail:\n\n```java\n@Test\nvoid fails_because_something_is_written_to_System_err(\n) throws Exception {\n  assertNothingWrittenToSystemErr(() -\u003e {\n    System.err.println(\"some text\");\n  });\n}\n\n@Test\nvoid fails_because_something_is_written_to_System_out(\n) throws Exception {\n  assertNothingWrittenToSystemOut(() -\u003e {\n    System.out.println(\"some text\");\n  });\n}\n```\n\nIf the code under test writes text to `System.err`/`System.out` then it is\nintermixed with the output of your build tool. Therefore you may want to avoid\nthat the code under test writes to `System.err`/`System.out`. You can achieve\nthis with the function `muteSystemErr`/`muteSystemOut`. E.g. the following tests\ndon't write anything to `System.err`/`System.out`:\n\n```java\n@Test\nvoid nothing_is_written_to_System_err(\n) throws Exception {\n  muteSystemErr(() -\u003e {\n    System.err.println(\"some text\");\n  });\n}\n\n@Test\nvoid nothing_is_written_to_System_out(\n) throws Exception {\n  muteSystemOut(() -\u003e {\n    System.out.println(\"some text\");\n  });\n}\n```\n\n### System.in\n\nInteractive command-line applications read from `System.in`. If you write such\napplications you need to provide input to these applications. You can specify\nthe lines that are available from `System.in` with the method\n`withTextFromSystemIn`\n\n```java\n@Test\nvoid Scanner_reads_text_from_System_in(\n) throws Exception {\n  withTextFromSystemIn(\"first line\", \"second line\")\n    .execute(() -\u003e {\n      Scanner scanner = new Scanner(System.in);\n      scanner.nextLine();\n      assertEquals(\"second line\", scanner.nextLine());\n    });\n}\n```\n\nFor a complete test coverage you may also want to simulate `System.in` throwing\nexceptions when the application reads from it. You can specify such an\nexception (either `RuntimeException` or `IOException`) after specifying the\ntext. The exception will be thrown by the next `read` after the text has been\nconsumed.\n\n```java\n@Test\nvoid System_in_throws_IOException(\n) throws Exception {\n  withTextFromSystemIn(\"first line\", \"second line\")\n    .andExceptionThrownOnInputEnd(new IOException())\n    .execute(() -\u003e {\n      Scanner scanner = new Scanner(System.in);\n      scanner.nextLine();\n      scanner.nextLine();\n      assertThrows(\n        IOException.class,\n        () -\u003e scanner.readLine()\n      );\n  });\n}\n\n@Test\nvoid System_in_throws_RuntimeException(\n) throws Exception {\n  withTextFromSystemIn(\"first line\", \"second line\")\n    .andExceptionThrownOnInputEnd(new RuntimeException())\n    .execute(() -\u003e {\n      Scanner scanner = new Scanner(System.in);\n      scanner.nextLine();\n      scanner.nextLine();\n      assertThrows(\n        RuntimeException.class,\n        () -\u003e scanner.readLine()\n      );\n    });\n}\n```\n\nYou can write a test that throws an exception immediately by not providing any\ntext.\n\n```java\nwithTextFromSystemIn()\n  .andExceptionThrownOnInputEnd(...)\n  .execute(() -\u003e {\n    Scanner scanner = new Scanner(System.in);\n    assertThrows(\n      ...,\n      () -\u003e scanner.readLine()\n    );\n  });\n```\n\n### Security Manager\n\nThe function `withSecurityManager` lets you specify the `SecurityManager` that\nis returned by `System.getSecurityManger()` while your code under test is\nexecuted.\n\n```java\n@Test\nvoid execute_code_with_specific_SecurityManager(\n) throws Exception {\n  SecurityManager securityManager = new ASecurityManager();\n  withSecurityManager(\n    securityManager,\n    () -\u003e {\n      //code under test\n      //e.g. the following assertion is met\n      assertSame(\n        securityManager,\n        System.getSecurityManager()\n      );\n    }\n  );\n}\n```\n\nAfter `withSecurityManager(...)` is executed`System.getSecurityManager()`\nreturns the original security manager again.\n\n\n## Contributing\n\nYou have three options if you have a feature request, found a bug or\nsimply have a question about System Lambda.\n\n* [Write an issue.](https://github.com/stefanbirkner/system-lambda/issues/new)\n* Create a pull request. (See [Understanding the GitHub Flow](https://guides.github.com/introduction/flow/index.html))\n* [Write a mail to mail@stefan-birkner.de](mailto:mail@stefan-birkner.de)\n\n\n## Development Guide\n\nSystem Lambda is built with [Maven](http://maven.apache.org/) and must be\ncompiled under JDK 8. If you want to contribute code then\n\n* Please write a test for your change.\n* Ensure that you didn't break the build by running `mvnw clean verify -Dgpg.skip`.\n* Fork the repo and create a pull request. (See [Understanding the GitHub Flow](https://guides.github.com/introduction/flow/index.html))\n\nThe basic coding style is described in the\n[EditorConfig](http://editorconfig.org/) file `.editorconfig`.\n\nSystem Lambda supports [GitHub Actions](https://help.github.com/en/actions)\n(Linux) and [AppVeyor](http://www.appveyor.com/) (Windows) for continuous\nintegration. Each pull request is automatically built by both CI servers.\nGitHub Actions tests with several Java versions (see Enhanced Testing) while\nAppVeyor tests with Java 8 only.\n\n### Project Decisions\n\nThere are decision records for some decisions that had been made for System\nLambda. They are stored in the folder\n[doc/Decision Records](doc/Decision%20Records)\n\n### Build with Docker\n\nThe script\n\n    ./scripts/mvn_in_docker.sh clean verify -Dgpg.skip\n\nbuilds System Lambda inside a Docker container. It uses your Maven local\nrepository. This is helpful if you have a Linux or macOS without JDK 8.\n\n### Enhanced Testing\n\nSystem Lambda is built with Java 8 and relies on JDK internals that are not\navailable from Java 16 on (unless you run Java with additional flags). We verify\nthat System Lambda works with newer Java versions by building it with OpenJDK 8\nand executing tests with newer versions of OpenJDK. All this work is put into a\nscript that you can run with\n\n    ./scripts/test.sh\n\nThe script uses Docker for running the tests.\n\n\n## Release Guide\n\n* Select a new version according to the\n  [Semantic Versioning 2.0.0 Standard](http://semver.org/).\n* Update `Changelog.md`.\n* Set the new version in `pom.xml` and in the `Installation` section of\n  this readme.\n* Commit the modified `Changelog.md`, `pom.xml` and `README.md`.\n* Run `mvnw clean deploy` with JDK 8.\n* Add a tag for the release: `git tag system-lambda-X.X.X`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefanbirkner%2Fsystem-lambda","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstefanbirkner%2Fsystem-lambda","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefanbirkner%2Fsystem-lambda/lists"}