Use the open-source free `coverlet` toolchain for .NET code coverage.
Detect Static Dependencies
Scan C# source files for hard-to-test static dependencies — DateTime.Now/UtcNow, File.*, Directory.*, Environment.*, HttpClient, Console.*, Process.*, and other untestable statics. Produces a ranked report of static call sites by frequency. USE FOR: find untestable statics, scan for static dependencies, testability audit, identify hard-to-mock code, find DateTime.Now usage, detect static coupling, testability report, static analysis for testability. DO NOT USE FOR: generating wrappers (use generate-testability-wrappers), migrating code (use migrate-static-to-wrapper), general code review, or finding statics that are already behind abstractions.
Workflow
Step 1: Determine scan scope
Resolve the target to a set of .cs files:
- If a
.csfile, scan that single file. - If a directory, scan all
.csfiles recursively (excludingobj/,bin/). - If a
.csproj, find its directory and scan.csfiles within. - If a
.sln, parse it, find all project directories, and scan.csfiles across all projects.
Always exclude obj/, bin/, and any user-specified exclusion patterns.
Step 2: Search for static dependency patterns
Scan each file for calls matching these categories:
| Category | Patterns to search for | Recommended replacement | |----------|----------------------|------------------------| | Time | DateTime.Now, DateTime.UtcNow, DateTime.Today, DateTimeOffset.Now, DateTimeOffset.UtcNow, Task.Delay(, new CancellationTokenSource(TimeSpan | TimeProvider (.NET 8+) | | File System | File.ReadAllText(, File.WriteAllText(, File.Exists(, File.Delete(, File.Copy(, File.Move(, Directory.Exists(, Directory.CreateDirectory(, Directory.GetFiles(, Directory.Delete(, Path.Combine(, Path.GetTempPath( | IFileSystem (System.IO.Abstractions NuGet) | | Environment | Environment.GetEnvironmentVariable(, Environment.SetEnvironmentVariable(, Environment.MachineName, Environment.UserName, Environment.CurrentDirectory, Environment.Exit( | Custom IEnvironmentProvider | | Network | new HttpClient(, HttpClient.GetAsync(, HttpClient.PostAsync(, HttpClient.SendAsync( | IHttpClientFactory (built-in) | | Console | Console.WriteLine(, Console.ReadLine(, Console.Write(, Console.ReadKey( | IConsole wrapper or ILogger | | Process | Process.Start(, Process.GetCurrentProcess(, Process.GetProcessesByName( | Custom IProcessRunner |
Step 3: Aggregate and rank results
Count each static call pattern across the entire scan scope. Produce a summary with:
- Category summary — total call sites per category (time, filesystem, env, etc.)
- Top patterns — the 10 most frequent individual patterns ranked by count
- Most affected files — files with the highest number of static dependencies
- Existing abstractions available — for each category, note the recommended .NET abstraction:
- Time → TimeProvider (built-in since .NET 8) - File system → System.IO.Abstractions (NuGet package) - HTTP → IHttpClientFactory (built-in) - Environment → custom IEnvironmentProvider - Console → custom IConsole or ILogger - Process → custom IProcessRunner
Step 4: Present the report
Format the output as a structured report:
Related skills
Write, run, or repair .NET tests that use MSTest.
Write, run, or repair .NET tests that use NUnit.