# Stryker.NET and the parts of it that live in other repositories

> Stryker.NET inserts temporary bugs into C# source so you can see which ones your assertions miss. This repository ships one three-line recipe and almost no configuration of its own, and its compatibility table certifies only dotnet core 3.1 and dotnet framework 4.8.

**stryker-mutator/stryker-net** — Mutation testing for .NET core and .NET framework!

- Repository: https://github.com/stryker-mutator/stryker-net
- Website: https://stryker-mutator.io
- Stars: 2,107 · Forks: 255
- Language: C#
- License: Apache-2.0
- Published: 2026-10-14 · Updated: 2026-10-14 · Language: en
- Canonical page: https://hysenlabs.com/projects/stryker-mutator-stryker-net

## One command, run from the unit test project folder

Coverage tells you a line ran. It does not tell you whether an assertion would fail when that line is wrong, and that gap is what Stryker.NET exists to close. Stryker defines itself in a single sentence: it allows you to test your tests by temporarily inserting bugs in your source code. Each inserted defect is a mutant, your existing suite runs against the altered code, and the ones your assertions fail to catch are handed back to you.

Getting it onto a machine takes three shell lines: install the tool globally, move into the folder holding the unit test project, then run it.

```bash
dotnet tool install -g dotnet-stryker
cd /my/unit/test/project/folder
dotnet stryker
```

That middle line carries more weight than it looks. No path argument, solution switch or output option appears anywhere in that recipe, so the working directory is the only thing selecting which project gets mutated. A solution holding twenty test projects means running this twenty times over, one report each time.

## The compatibility table promises more than it proves

Two lists sit in the compatibility section and they do not meet. The minimum target version column names dotnet core 1.1, dotnet framework 4.5 and dotnet standard 1.3. The tested-against column names dotnet core 3.1 and dotnet framework 4.8, and stops there.

That leaves a hole rather than a range. A test project on any runtime between dotnet core 1.1 and dotnet core 3.1 sits above the stated floor but below the tested line, so nothing in the repository promises it works and nothing demonstrates that it does. dotnet standard 1.3 fares worse. It is the one target that spans both core and framework, yet the tested column carries no standard entry at all, which leaves the most portable-looking option as the one with the thinnest evidence behind it.

Read the ceiling as the real limit. The newest runtime anyone is told has been exercised is dotnet core 3.1, and the newest framework is 4.8. If your suite targets something later, the accurate statement is that this repository does not cover your case, and no file in the tree closes the gap.

## Mutators are source files, not configuration switches

Mutations are not a list you switch on. They are code in this repository, which is why adding_a_mutator.md sits at the root beside README.md where a config file enumerating operator names would sit. The operator names themselves live on stryker-mutator.io; the implementations live under src/.

The consequence for a user is blunt. If your codebase leans on an idiom the current mutators do not cover, no local configuration will add one. You write the mutator, follow the contribution guide at /CONTRIBUTING.md, and wait for whoever MAINTAINERS.md names to read it. CODE_OF_CONDUCT.md and AGENTS.md sit next to those files, and the repository carries a hacktoberfest topic. All of that describes a project absorbing code patches rather than configuration requests, so a custom operator costs review time, not a config edit.

## The HTML report is maintained in another repository

Reporters split along the same line as mutators. The reporter list lives on stryker-mutator.io, and one case is handed to a different project entirely: issues about the HTML report belong in mutation-testing-elements, not in this repository's tracker. A rendering bug you hit in a report cannot be fixed here.

The badges at the top of the README show how wide that split runs. The NuGet badge points at the dotnet-stryker package on nuget.org, the build and test badges point at Azure DevOps, and the mutation testing badge resolves through badge-api.stryker-mutator.io to a public report for the master branch at dashboard.stryker-mutator.io. A tool whose whole job is grading other people's test suites publishes its own result in the open, which is a fair baseline to hold the one you install to.

A fifth badge rounds out that row, a Slack badge pointing at a shared invite for the stryker-mutator workspace. It is the practical route for questions about mutant behaviour that no file in this repository answers.

## A Node manifest decides the dotnet tool version

This is a .NET tool whose version counter is a Node manifest. The root package.json is marked private, the npm signal that it is never published, yet it carries 5.0.0 twice: once in the version field and once in a versionPrefix field paired with an empty versionSuffix. Both values match the dotnet-stryker@5.0.0 that users install, so the shipped version is decided by a file npm will not touch. Here is that file, trimmed to the keys that matter.

```json
{
    "private": true,
    "version": "5.0.0",
    "versionPrefix": "5.0.0",
    "versionSuffix": "",
    "scripts": {
        "prepare-release": "node prepare-release.js"
    },
    "devDependencies": {
        "conventional-changelog-angular": "^8.3.1",
        "conventional-recommended-bump": "^6.1.0",
        "semver": "^7.6.0"
    }
}
```

The script it calls is prepare-release.js, wired to the prepare-release entry in the scripts object, and its devDependencies are conventional-changelog-angular at ^8.3.1, conventional-recommended-bump at ^6.1.0 and semver at ^7.6.0, which makes a conventional-commit pipeline out of a Node file that ships a C# tool. RELEASING.md documents the procedure. The last push was on 2026-10-06, about four weeks after the dotnet-stryker@5.0.0 version dated 2026-09-11.

## Stryker.NET runs against itself in PowerShell scripts

A mutation testing tool that never runs on itself would be an odd thing to trust, and this one does. integration-tests.ps1 drives the integration suite, and stryker-on-stryker.ps1 points the tool at its own source. Around them the pipeline shape is visible: azure-pipelines.yml at the root, shared definitions under pipeline-templates/, and integrationtest/ holding the tests those scripts exercise. The build and test badges resolve to Azure DevOps definitionId=4 on master.

Editor and container provisioning sits here too: .devcontainer/, .vscode/, .editorconfig, .gitattributes and stryker-net.code-workspace. What is absent matters just as much. Nothing in the README gives you a CI recipe for a consumer project, a pipeline template to copy, or an environment variable for a headless run. Wiring Stryker.NET into a build means reading the maintainers' Azure Pipelines definitions and translating them yourself.

## JavaScript and Scala have their own separate tools

The alternatives named here are real, and none of them is a different mutation engine. The README points JavaScript and TypeScript users at a project hosted under stryker-mutator.github.io/stryker, and Scala users at one called stryker4s. Those live in separate repositories with their own mutators and their own commands, so no configuration file and no mutator carries across that boundary.

The approach inside all three is identical: insert a deliberate defect, run the suite, report the mutants that survived. What changes is the host runtime, and that is what the compatibility table is really about. Its dotnet core and dotnet framework rows say nothing about a JavaScript or Scala build, which is exactly why the routing exists in the first place. If your code is not C#, this repository is the wrong door, and reading its compatibility section will not help you.

## The README ends where the website begins

Count what a new user actually receives here: three shell lines, a two-row compatibility table, and a column of links to stryker-mutator.io for configuration, mutations, reporters, migration and background. Not one configuration key appears. No reporter is named, no mutant operator is listed, no score threshold or output format is written down, and no rollback or partial-run option exists in the text.

That is a real evaluation cost. From this tree alone you cannot tell whether the HTML reporter is slow on a large suite, whether mutants are cached between runs, or what a passing run even looks like. The public dashboard proves the project tracks its own score, yet the field names behind that badge are not recorded here.

One detail rewards a closer look. A docs/ directory sits in the tree, yet every documentation link in the README points outward to stryker-mutator.io instead of into it, and what that folder contains is never stated. The same holds for package-lock.json, which exists next to a manifest npm never publishes. This repository is built to be consumed as a tool, and everything a reader needs beyond that lives somewhere else.

Two consequences follow: confirm the config keys on the site before you budget CI minutes for the tool, and allow for migration work if you arrive from a 4.x version, since a migration guide is kept for exactly that case.

## Conclusion

Stryker.NET suits a .NET team whose coverage number has stopped telling it anything, and it does nothing for a JavaScript or Scala codebase, which the README routes to separate projects. Before you put it in CI, confirm three things this repository does not record: the configuration keys, the score your own suite can reach, and the reporter list. Check your runtime against the compatibility table, which names dotnet core 3.1 and dotnet framework 4.8 as tested and nothing later. Then run dotnet stryker in one test project and read what it prints before wiring anything.

## FAQ

### Which .NET versions does Stryker.NET claim to support?

It lists minimum target versions of dotnet core 1.1, dotnet framework 4.5 and dotnet standard 1.3, and says it is tested against dotnet core 3.1 and dotnet framework 4.8. No dotnet standard version appears in the tested list.

### What licence is Stryker.NET distributed under?

Apache-2.0, with the terms sitting in the LICENSE file at the repository root.

### Can Stryker.NET mutate a JavaScript or Scala project?

Not from this repository. JavaScript and TypeScript users are pointed to a project under stryker-mutator.github.io/stryker, and Scala users to stryker4s, each a separate codebase with its own command.

### Where should I report a bug in the Stryker.NET HTML report?

Open it in the mutation-testing-elements repository rather than in stryker-mutator/stryker-net, because report rendering lives in that other project.

### How do I add a new mutation operator to Stryker.NET?

By writing it in this codebase and sending it upstream. adding_a_mutator.md sits at the repository root and CONTRIBUTING.md holds the contribution guide, so operators arrive as code rather than as configuration.

### Does dotnet stryker accept a path to my solution?

No such option appears in the documented recipe. The tool is installed globally, you change into the unit test project folder, and dotnet stryker runs there, so the working directory is what selects the project.

## Sources

- [License: Apache-2.0](https://github.com/stryker-mutator/stryker-net/blob/master/LICENSE)
- [Project website](https://stryker-mutator.io)
- [README](https://github.com/stryker-mutator/stryker-net/blob/master/README.md)
- [Releases](https://github.com/stryker-mutator/stryker-net/releases)
- [stryker-mutator/stryker-net on GitHub](https://github.com/stryker-mutator/stryker-net)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/stryker-mutator-stryker-net
