Repository: scala-steward-org/scala-steward
Pull request #1888 (2021-01-17 21:13:47)

Reuse Context in tests
This reduces duplication in `Context` and `MockContext` which both contained code to initialize classes. The first does it for the production `F` while the latter does it for `MockEff`. This change splits `Context.create` into two functions, `step0` and `step1`, such that `step1` takes the classes we want or need to mock in tests as parameters. `step1` is then used in `MockContext` to create a `Context[MockEff]` whose members are used in test classes instead of the previously manually initialized instances in `MockContext`.

codecov[bot]: # [Codecov](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888?src=pr&el=h1) Report
> Merging [#1888](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888?src=pr&el=desc) (7276c0f) into [master](https://codecov.io/gh/scala-steward-org/scala-steward/commit/26591b84f4990fc5a5f5441b931889865132321f?el=desc) (26591b8) will **increase** coverage by `1.29%`.
> The diff coverage is `76.47%`.

[![Impacted file tree graph](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/graphs/tree.svg?width=650&height=150&src=pr&token=udzMsc1Dne)](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1888      +/-   ##
==========================================
+ Coverage   75.51%   76.80%   +1.29%     
==========================================
  Files         129      129              
  Lines        2185     2212      +27     
  Branches       54       59       +5     
==========================================
+ Hits         1650     1699      +49     
+ Misses        535      513      -22     
```


| [Impacted Files](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [...re/src/main/scala/org/scalasteward/core/Main.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS9NYWluLnNjYWxh) | `0.00% <0.00%> (ø)` | |
| [...la/org/scalasteward/core/application/Context.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS9hcHBsaWNhdGlvbi9Db250ZXh0LnNjYWxh) | `82.69% <75.00%> (+82.69%)` | :arrow_up: |
| [.../scala/org/scalasteward/core/util/UrlChecker.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS91dGlsL1VybENoZWNrZXIuc2NhbGE=) | `100.00% <100.00%> (+12.50%)` | :arrow_up: |
| [...scalasteward/core/vcs/github/GitHubAppApiAlg.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS92Y3MvZ2l0aHViL0dpdEh1YkFwcEFwaUFsZy5zY2FsYQ==) | `4.76% <0.00%> (+4.76%)` | :arrow_up: |
| [...g/scalasteward/core/vcs/github/GitHubAuthAlg.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS92Y3MvZ2l0aHViL0dpdEh1YkF1dGhBbGcuc2NhbGE=) | `5.00% <0.00%> (+5.00%)` | :arrow_up: |
| [.../scalasteward/core/repocache/RefreshErrorAlg.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS9yZXBvY2FjaGUvUmVmcmVzaEVycm9yQWxnLnNjYWxh) | `6.66% <0.00%> (+6.66%)` | :arrow_up: |
| [...ala/org/scalasteward/core/application/Config.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS9hcHBsaWNhdGlvbi9Db25maWcuc2NhbGE=) | `100.00% <0.00%> (+8.82%)` | :arrow_up: |
| [...scala/org/scalasteward/core/vcs/VCSSelection.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS92Y3MvVkNTU2VsZWN0aW9uLnNjYWxh) | `13.63% <0.00%> (+13.63%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888?src=pr&el=footer). Last update [26591b8...7276c0f](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1888?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/modules/core/src/main/scala/org/scalasteward/core/Main.scala b/modules/core/src/main/scala/org/scalasteward/core/Main.scala
index 5c29ed69..74409f0d 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/Main.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/Main.scala
@@ -22,7 +22,7 @@ import org.scalasteward.core.application.{Cli, Context}
 object Main extends IOApp {
   override def run(args: List[String]): IO[ExitCode] =
     Cli.parseArgs(args) match {
-      case Cli.ParseResult.Success(args) => Context.create[IO](args).use(_.runF)
+      case Cli.ParseResult.Success(args) => Context.step0[IO](args).use(_.stewardAlg.runF)
       case Cli.ParseResult.Help(help)    => IO(Console.out.println(help)).as(ExitCode.Success)
       case Cli.ParseResult.Error(error)  => IO(Console.err.println(error)).as(ExitCode.Error)
     }
diff --git a/modules/core/src/main/scala/org/scalasteward/core/application/Context.scala b/modules/core/src/main/scala/org/scalasteward/core/application/Context.scala
index abd5a23a..6f1f54fb 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/application/Context.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/application/Context.scala
@@ -46,30 +46,68 @@ import org.scalasteward.core.vcs.data.Repo
 import org.scalasteward.core.vcs.github.{GitHubAppApiAlg, GitHubAuthAlg}
 import org.scalasteward.core.vcs.{VCSApiAlg, VCSExtraAlg, VCSRepoAlg, VCSSelection}
 
+final class Context[F[_]](implicit
+    val buildToolDispatcher: BuildToolDispatcher[F],
+    val coursierAlg: CoursierAlg[F],
+    val dateTimeAlg: DateTimeAlg[F],
+    val editAlg: EditAlg[F],
+    val fileAlg: FileAlg[F],
+    val filterAlg: FilterAlg[F],
+    val gitAlg: GitAlg[F],
+    val hookExecutor: HookExecutor[F],
+    val logger: Logger[F],
+    val mavenAlg: MavenAlg[F],
+    val migrationAlg: MigrationAlg,
+    val migrationsLoader: MigrationsLoader[F],
+    val millAlg: MillAlg[F],
+    val pruningAlg: PruningAlg[F],
+    val pullRequestRepository: PullRequestRepository[F],
+    val repoConfigAlg: RepoConfigAlg[F],
+    val sbtAlg: SbtAlg[F],
+    val scalafmtAlg: ScalafmtAlg[F],
+    val stewardAlg: StewardAlg[F],
+    val updateAlg: UpdateAlg[F],
+    val vcsRepoAlg: VCSRepoAlg[F],
+    val workspaceAlg: WorkspaceAlg[F]
+)
+
 object Context {
-  def create[F[_]: ConcurrentEffect: ContextShift: Parallel: Timer](
+  def step0[F[_]: ConcurrentEffect: ContextShift: Parallel: Timer](
       args: Cli.Args
-  ): Resource[F, StewardAlg[F]] =
+  ): Resource[F, Context[F]] =
     for {
       blocker <- Blocker[F]
-      implicit0(logger: Logger[F]) <- Resource.liftF(Slf4jLogger.create[F])
-      _ <- Resource.liftF(printBanner[F])
       config = Config.from(args)
+      implicit0(logger: Logger[F]) <- Resource.liftF(Slf4jLogger.create[F])
       implicit0(client: Client[F]) <- OkHttpBuilder.withDefaultClient[F](blocker).map(_.create)
-      implicit0(urlChecker: UrlChecker[F]) <- UrlChecker.create[F](config)
       implicit0(fileAlg: FileAlg[F]) = FileAlg.create[F]
       implicit0(processAlg: ProcessAlg[F]) = ProcessAlg.create[F](blocker, config.processCfg)
+      implicit0(urlChecker: UrlChecker[F]) <- UrlChecker.create[F](config)
       implicit0(workspaceAlg: WorkspaceAlg[F]) = WorkspaceAlg.create[F](config)
+      context <- Resource.liftF(step1[F](config))
+    } yield context
+
+  def step1[F[_]](config: Config)(implicit
+      client: Client[F],
+      contextShift: ContextShift[F],
+      fileAlg: FileAlg[F],
+      logger: Logger[F],
+      parallel: Parallel[F],
+      processAlg: ProcessAlg[F],
+      urlChecker: UrlChecker[F],
+      workspaceAlg: WorkspaceAlg[F],
+      F: Sync[F]
+  ): F[Context[F]] =
+    for {
+      _ <- printBanner[F]
+      vcsUser <- config.vcsUser[F]
+      implicit0(migrationsLoader: MigrationsLoader[F]) = new MigrationsLoader[F]
       implicit0(migrationAlg: MigrationAlg) <-
-        Resource.liftF(new MigrationsLoader[F].loadAll(config.scalafixCfg).map(new MigrationAlg(_)))
-      implicit0(artifactMigration: ArtifactMigrations) <-
-        Resource.liftF(ArtifactMigrations.create[F](config))
-      vcsUser <- Resource.liftF(config.vcsUser[F])
+        migrationsLoader.loadAll(config.scalafixCfg).map(new MigrationAlg(_))
+      implicit0(artifactMigration: ArtifactMigrations) <- ArtifactMigrations.create[F](config)
       kvsPrefix = Some(config.vcsType.asString)
-      pullRequestsStore <- Resource.liftF(
-        CachingKeyValueStore.wrap(
-          new JsonKeyValueStore[F, Repo, Map[Uri, PullRequestData]]("pull_requests", "2", kvsPrefix)
-        )
+      pullRequestsStore <- CachingKeyValueStore.wrap(
+        new JsonKeyValueStore[F, Repo, Map[Uri, PullRequestData]]("pull_requests", "2", kvsPrefix)
       )
     } yield {
       implicit val dateTimeAlg: DateTimeAlg[F] = DateTimeAlg.create[F]
@@ -103,7 +141,8 @@ object Context {
       implicit val nurtureAlg: NurtureAlg[F] = new NurtureAlg[F](config)
       implicit val pruningAlg: PruningAlg[F] = new PruningAlg[F]
       implicit val gitHubAppApiAlg: GitHubAppApiAlg[F] = new GitHubAppApiAlg[F](config.vcsApiHost)
-      new StewardAlg[F](config)
+      implicit val stewardAlg: StewardAlg[F] = new StewardAlg[F](config)
+      new Context[F]
     }
 
   private def printBanner[F[_]](implicit logger: Logger[F]): F[Unit] = {
diff --git a/modules/core/src/main/scala/org/scalasteward/core/util/UrlChecker.scala b/modules/core/src/main/scala/org/scalasteward/core/util/UrlChecker.scala
index 342ad19a..9aba24d0 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/util/UrlChecker.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/util/UrlChecker.scala
@@ -16,8 +16,7 @@
 
 package org.scalasteward.core.util
 
-import cats.MonadThrow
-import cats.effect.{Async, Resource}
+import cats.effect.{Async, Resource, Sync}
 import cats.syntax.all._
 import com.github.benmanes.caffeine.cache.Caffeine
 import io.chrisdavenport.log4cats.Logger
@@ -26,40 +25,39 @@ import org.http4s.{Method, Request, Status, Uri}
 import org.scalasteward.core.application.Config
 import scalacache.CatsEffect.modes._
 import scalacache.caffeine.CaffeineCache
-import scalacache.{Async => _, _}
+import scalacache.{Async => _, Sync => _, _}
 
-final class UrlChecker[F[_]](statusCache: Cache[Status])(implicit
-    client: Client[F],
-    logger: Logger[F],
-    mode: Mode[F],
-    F: MonadThrow[F]
-) {
-  def exists(url: Uri): F[Boolean] =
-    status(url).map(_ === Status.Ok).handleErrorWith { throwable =>
-      logger.debug(throwable)(s"Failed to check if $url exists").as(false)
-    }
-
-  private def status(url: Uri): F[Status] =
-    statusCache.cachingForMemoizeF(url.renderString)(None) {
-      client.status(Request[F](method = Method.HEAD, uri = url))
-    }
+trait UrlChecker[F[_]] {
+  def exists(url: Uri): F[Boolean]
 }
 
 object UrlChecker {
+  def buildCache[F[_]](config: Config)(implicit F: Sync[F]): F[CaffeineCache[Status]] =
+    F.delay {
+      val cache = Caffeine
+        .newBuilder()
+        .maximumSize(16384L)
+        .expireAfterWrite(config.cacheTtl.length, config.cacheTtl.unit)
+        .build[String, Entry[Status]]()
+      CaffeineCache(cache)
+    }
+
   def create[F[_]](config: Config)(implicit
       client: Client[F],
       logger: Logger[F],
       F: Async[F]
-  ): Resource[F, UrlChecker[F]] = {
-    val buildCache = F.delay {
-      CaffeineCache(
-        Caffeine
-          .newBuilder()
-          .maximumSize(16384L)
-          .expireAfterWrite(config.cacheTtl.length, config.cacheTtl.unit)
-          .build[String, Entry[Status]]()
-      )
+  ): Resource[F, UrlChecker[F]] =
+    Resource.make(buildCache(config))(_.close().void).map { statusCache =>
+      new UrlChecker[F] {
+        override def exists(url: Uri): F[Boolean] =
+          status(url).map(_ === Status.Ok).handleErrorWith { throwable =>
+            logger.debug(throwable)(s"Failed to check if $url exists").as(false)
+          }
+
+        private def status(url: Uri): F[Status] =
+          statusCache.cachingForMemoizeF(url.renderString)(None) {
+            client.status(Request[F](method = Method.HEAD, uri = url))
+          }
+      }
     }
-    Resource.make(buildCache)(_.close().void).map(new UrlChecker[F](_))
-  }
 }


Test patch:
diff --git a/modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala b/modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala
index 8a068e24..815b4aee 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala
@@ -4,7 +4,8 @@ import munit.FunSuite
 import org.scalasteward.core.buildtool.sbt.command._
 import org.scalasteward.core.buildtool.sbt.data.SbtVersion
 import org.scalasteward.core.data.{Resolver, Scope, Version}
-import org.scalasteward.core.mock.MockContext.{buildToolDispatcher, config}
+import org.scalasteward.core.mock.MockContext.config
+import org.scalasteward.core.mock.MockContext.context.buildToolDispatcher
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.scalafmt
 import org.scalasteward.core.vcs.data.Repo
diff --git a/modules/core/src/test/scala/org/scalasteward/core/buildtool/maven/MavenAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/buildtool/maven/MavenAlgTest.scala
index 9176b628..70fff1bf 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/buildtool/maven/MavenAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/buildtool/maven/MavenAlgTest.scala
@@ -3,6 +3,7 @@ package org.scalasteward.core.buildtool.maven
 import better.files.File
 import munit.FunSuite
 import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.context.mavenAlg
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.vcs.data.{BuildRoot, Repo}
 
diff --git a/modules/core/src/test/scala/org/scalasteward/core/buildtool/mill/MillAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/buildtool/mill/MillAlgTest.scala
index be906f03..74f0a708 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/buildtool/mill/MillAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/buildtool/mill/MillAlgTest.scala
@@ -2,7 +2,8 @@ package org.scalasteward.core.buildtool.mill
 
 import munit.FunSuite
 import org.scalasteward.core.buildtool.mill.MillAlg.extractDeps
-import org.scalasteward.core.mock.MockContext.{config, millAlg}
+import org.scalasteward.core.mock.MockContext.config
+import org.scalasteward.core.mock.MockContext.context.millAlg
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.vcs.data.{BuildRoot, Repo}
 
diff --git a/modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala
index 235fb36b..196bcbd2 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala
@@ -4,7 +4,8 @@ import cats.data.StateT
 import munit.FunSuite
 import org.scalasteward.core.buildtool.sbt.command._
 import org.scalasteward.core.data.{GroupId, Version}
-import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.context.sbtAlg
+import org.scalasteward.core.mock.MockContext.config
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.scalafix.Migration
 import org.scalasteward.core.util.Nel
diff --git a/modules/core/src/test/scala/org/scalasteward/core/coursier/CoursierAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/coursier/CoursierAlgTest.scala
index c6232133..adfd5cc4 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/coursier/CoursierAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/coursier/CoursierAlgTest.scala
@@ -5,7 +5,7 @@ import org.http4s.syntax.literals._
 import org.scalasteward.core.TestSyntax._
 import org.scalasteward.core.buildtool.sbt.data.{SbtVersion, ScalaVersion}
 import org.scalasteward.core.data.{ArtifactId, Dependency, GroupId}
-import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.context.coursierAlg
 import org.scalasteward.core.mock.MockState
 
 class CoursierAlgTest extends FunSuite {
diff --git a/modules/core/src/test/scala/org/scalasteward/core/edit/EditAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/edit/EditAlgTest.scala
index 0b4469f1..41e620bb 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/edit/EditAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/edit/EditAlgTest.scala
@@ -4,7 +4,8 @@ import better.files.File
 import munit.FunSuite
 import org.scalasteward.core.TestSyntax._
 import org.scalasteward.core.data.{GroupId, Update}
-import org.scalasteward.core.mock.MockContext.{config, editAlg, envVars}
+import org.scalasteward.core.mock.MockContext.context.editAlg
+import org.scalasteward.core.mock.MockContext.{config, envVars}
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.repoconfig.RepoConfig
 import org.scalasteward.core.scalafmt.scalafmtBinary
diff --git a/modules/core/src/test/scala/org/scalasteward/core/edit/hooks/HookExecutorTest.scala b/modules/core/src/test/scala/org/scalasteward/core/edit/hooks/HookExecutorTest.scala
index 5cebb6b0..65ed6cd0 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/edit/hooks/HookExecutorTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/edit/hooks/HookExecutorTest.scala
@@ -3,7 +3,8 @@ package org.scalasteward.core.edit.hooks
 import munit.FunSuite
 import org.scalasteward.core.TestSyntax._
 import org.scalasteward.core.data.Update
-import org.scalasteward.core.mock.MockContext.{envVars, hookExecutor, workspaceAlg}
+import org.scalasteward.core.mock.MockContext.context.{hookExecutor, workspaceAlg}
+import org.scalasteward.core.mock.MockContext.envVars
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.repoconfig.{RepoConfig, ScalafmtConfig}
 import org.scalasteward.core.scalafmt.{scalafmtArtifactId, scalafmtBinary, scalafmtGroupId}
diff --git a/modules/core/src/test/scala/org/scalasteward/core/io/FileAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/io/FileAlgTest.scala
index 7b33f2d4..e139d412 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/io/FileAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/io/FileAlgTest.scala
@@ -7,7 +7,7 @@ import org.http4s.Uri
 import org.scalacheck.Arbitrary
 import org.scalasteward.core.TestInstances.ioLogger
 import org.scalasteward.core.io.FileAlgTest.ioFileAlg
-import org.scalasteward.core.mock.MockContext.fileAlg
+import org.scalasteward.core.mock.MockContext.context.fileAlg
 import org.scalasteward.core.mock.MockState
 
 class FileAlgTest extends FunSuite {
diff --git a/modules/core/src/test/scala/org/scalasteward/core/mock/MockContext.scala b/modules/core/src/test/scala/org/scalasteward/core/mock/MockContext.scala
index dd37e653..533ac526 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/mock/MockContext.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/mock/MockContext.scala
@@ -1,97 +1,51 @@
 package org.scalasteward.core.mock
 
 import better.files.File
-import cats.Parallel
 import cats.effect.{BracketThrow, Sync}
+import cats.{Applicative, Parallel}
 import io.chrisdavenport.log4cats.Logger
-import org.http4s.Uri
+import org.http4s.client.Client
+import org.http4s.{HttpApp, Uri}
 import org.scalasteward.core.TestInstances.ioContextShift
 import org.scalasteward.core.application.Cli.EnvVar
-import org.scalasteward.core.application.{Cli, Config, SupportedVCS}
-import org.scalasteward.core.buildtool.BuildToolDispatcher
-import org.scalasteward.core.buildtool.maven.MavenAlg
-import org.scalasteward.core.buildtool.mill.MillAlg
-import org.scalasteward.core.buildtool.sbt.SbtAlg
-import org.scalasteward.core.coursier.{CoursierAlg, VersionsCache}
-import org.scalasteward.core.edit.EditAlg
-import org.scalasteward.core.edit.hooks.HookExecutor
-import org.scalasteward.core.git.{GenGitAlg, GitAlg}
+import org.scalasteward.core.application.{Cli, Config, Context, SupportedVCS}
 import org.scalasteward.core.io._
-import org.scalasteward.core.nurture.PullRequestRepository
-import org.scalasteward.core.persistence.JsonKeyValueStore
-import org.scalasteward.core.repocache.RepoCacheRepository
-import org.scalasteward.core.repoconfig.RepoConfigAlg
-import org.scalasteward.core.scalafix.{MigrationAlg, MigrationsLoader, MigrationsLoaderTest}
-import org.scalasteward.core.scalafmt.ScalafmtAlg
-import org.scalasteward.core.update.{ArtifactMigrations, FilterAlg, PruningAlg, UpdateAlg}
-import org.scalasteward.core.util.uri._
-import org.scalasteward.core.util.DateTimeAlg
-import org.scalasteward.core.vcs.VCSRepoAlg
+import org.scalasteward.core.scalafix.MigrationsLoaderTest
+import org.scalasteward.core.util.UrlChecker
 import org.scalasteward.core.vcs.data.AuthenticatedUser
 import scala.concurrent.duration._
 
 object MockContext {
-  val config: Config =
-    Config.from(
-      Cli.Args(
-        workspace = File.temp / "ws",
-        reposFile = File.temp / "repos.md",
-        defaultRepoConf = Some(File.temp / "default.scala-steward.conf"),
-        gitAuthorName = "Bot Doe",
-        gitAuthorEmail = "bot@example.org",
-        vcsType = SupportedVCS.GitHub,
-        vcsApiHost = Uri(),
-        vcsLogin = "bot-doe",
-        gitAskPass = File.temp / "askpass.sh",
-        enableSandbox = Some(true),
-        envVar = List(
-          EnvVar("VAR1", "val1"),
-          EnvVar("VAR2", "val2")
-        ),
-        cacheTtl = 1.hour,
-        githubAppId = Some(12345678),
-        githubAppKeyFile = Some(File("example_app_key"))
-      )
-    )
-
+  val args: Cli.Args = Cli.Args(
+    workspace = File.temp / "ws",
+    reposFile = File.temp / "repos.md",
+    defaultRepoConf = Some(File.temp / "default.scala-steward.conf"),
+    gitAuthorName = "Bot Doe",
+    gitAuthorEmail = "bot@example.org",
+    vcsType = SupportedVCS.GitHub,
+    vcsApiHost = Uri(),
+    vcsLogin = "bot-doe",
+    gitAskPass = File.temp / "askpass.sh",
+    enableSandbox = Some(true),
+    envVar = List(EnvVar("VAR1", "val1"), EnvVar("VAR2", "val2")),
+    cacheTtl = 1.hour,
+    githubAppId = Some(12345678),
+    githubAppKeyFile = Some(File("example_app_key"))
+  )
+  val config: Config = Config.from(args)
   val envVars = List(s"GIT_ASKPASS=${config.gitCfg.gitAskPass}", "VAR1=val1", "VAR2=val2")
+  val user: AuthenticatedUser = AuthenticatedUser("scala-steward", "token")
 
   implicit val mockEffBracketThrow: BracketThrow[MockEff] = Sync[MockEff]
   implicit val mockEffParallel: Parallel[MockEff] = Parallel.identity
 
-  implicit val fileAlg: FileAlg[MockEff] = new MockFileAlg
-  implicit val mockLogger: Logger[MockEff] = new MockLogger
-  implicit val processAlg: ProcessAlg[MockEff] = MockProcessAlg.create(config.processCfg)
-  implicit val workspaceAlg: WorkspaceAlg[MockEff] = new MockWorkspaceAlg
+  implicit private val client: Client[MockEff] = Client.fromHttpApp(HttpApp.notFound)
+  implicit private val fileAlg: FileAlg[MockEff] = new MockFileAlg
+  implicit private val logger: Logger[MockEff] = new MockLogger
+  implicit private val processAlg: ProcessAlg[MockEff] = MockProcessAlg.create(config.processCfg)
+  implicit private val urlChecker: UrlChecker[MockEff] = _ => Applicative[MockEff].pure(false)
+  implicit private val workspaceAlg: WorkspaceAlg[MockEff] = new MockWorkspaceAlg
 
-  implicit val coursierAlg: CoursierAlg[MockEff] = CoursierAlg.create
-  implicit val dateTimeAlg: DateTimeAlg[MockEff] = DateTimeAlg.create
-  implicit val gitAlg: GitAlg[MockEff] = GenGitAlg.create(config.gitCfg)
-  implicit val hookExecutor: HookExecutor[MockEff] = new HookExecutor[MockEff]
-  implicit val user: AuthenticatedUser = AuthenticatedUser("scala-steward", "token")
-  implicit val vcsRepoAlg: VCSRepoAlg[MockEff] = new VCSRepoAlg[MockEff](config)
-  implicit val repoConfigAlg: RepoConfigAlg[MockEff] = new RepoConfigAlg[MockEff](config)
-  implicit val scalafmtAlg: ScalafmtAlg[MockEff] = ScalafmtAlg.create
-  val migrationsLoader: MigrationsLoader[MockEff] = new MigrationsLoader[MockEff]
-  implicit val migrationAlg: MigrationAlg = migrationsLoader
-    .loadAll(config.scalafixCfg)
-    .map(new MigrationAlg(_))
-    .runA(MigrationsLoaderTest.mockState)
-    .unsafeRunSync()
-  implicit val cacheRepository: RepoCacheRepository[MockEff] =
-    new RepoCacheRepository[MockEff](new JsonKeyValueStore("repo_cache", "1"))
-  implicit val filterAlg: FilterAlg[MockEff] = new FilterAlg[MockEff]
-  implicit val versionsCache: VersionsCache[MockEff] =
-    new VersionsCache[MockEff](config.cacheTtl, new JsonKeyValueStore("versions", "1"))
-  implicit val artifactMigrations: ArtifactMigrations =
-    ArtifactMigrations.create[MockEff](config).runA(MockState.empty).unsafeRunSync()
-  implicit val updateAlg: UpdateAlg[MockEff] = new UpdateAlg[MockEff]
-  implicit val mavenAlg: MavenAlg[MockEff] = MavenAlg.create(config)
-  implicit val sbtAlg: SbtAlg[MockEff] = SbtAlg.create(config)
-  implicit val millAlg: MillAlg[MockEff] = MillAlg.create
-  implicit val buildToolDispatcher: BuildToolDispatcher[MockEff] = BuildToolDispatcher.create
-  implicit val editAlg: EditAlg[MockEff] = new EditAlg[MockEff]
-  implicit val pullRequestRepository: PullRequestRepository[MockEff] =
-    new PullRequestRepository[MockEff](new JsonKeyValueStore("pull_requests", "2"))
-  implicit val pruningAlg: PruningAlg[MockEff] = new PruningAlg[MockEff]
+  val context: Context[MockEff] =
+    Context.step1[MockEff](config).runA(MigrationsLoaderTest.mockState).unsafeRunSync()
 }
diff --git a/modules/core/src/test/scala/org/scalasteward/core/nurture/PullRequestRepositoryTest.scala b/modules/core/src/test/scala/org/scalasteward/core/nurture/PullRequestRepositoryTest.scala
index 348dba92..81bc7ce5 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/nurture/PullRequestRepositoryTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/nurture/PullRequestRepositoryTest.scala
@@ -1,13 +1,13 @@
 package org.scalasteward.core.nurture
 
 import munit.FunSuite
-import org.http4s.Uri
 import org.http4s.syntax.literals._
 import org.scalasteward.core.TestSyntax._
 import org.scalasteward.core.data.Update
 import org.scalasteward.core.git.Sha1
 import org.scalasteward.core.git.Sha1.HexString
-import org.scalasteward.core.mock.MockContext.{config, pullRequestRepository}
+import org.scalasteward.core.mock.MockContext.config
+import org.scalasteward.core.mock.MockContext.context.pullRequestRepository
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.util.Nel
 import org.scalasteward.core.vcs.data.{PullRequestNumber, PullRequestState, Repo}
@@ -16,148 +16,135 @@ class PullRequestRepositoryTest extends FunSuite {
   private def checkCommands(state: MockState, commands: Vector[List[String]]): Unit =
     assertEquals(state.copy(files = Map.empty), MockState.empty.copy(commands = commands))
 
-  withStoreData { (repo, url, sha1, number) =>
-    test("createOrUpdate >> findPullRequest >> lastPullRequestCreatedAt") {
-      val update = TestData.Updates.PortableScala
-
-      val p = for {
-        _ <- pullRequestRepository.createOrUpdate(
-          repo,
-          url,
-          sha1,
-          update,
-          PullRequestState.Open,
-          number
-        )
-        result <- pullRequestRepository.findLatestPullRequest(repo, update.crossDependency, "1.0.0")
-        createdAt <- pullRequestRepository.lastPullRequestCreatedAt(repo)
-      } yield (result, createdAt)
-      val (state, (result, createdAt)) = p.run(MockState.empty).unsafeRunSync()
-
-      val store = config.workspace / "store/pull_requests/v2/typelevel/cats/pull_requests.json"
-      assertEquals(result, Some((url, sha1, PullRequestState.Open)))
-      assert(createdAt.isDefined)
-
-      checkCommands(
-        state,
-        Vector(
-          List("read", store.toString),
-          List("write", store.toString),
-          List("read", store.toString),
-          List("read", store.toString)
-        )
+  private val url = uri"https://github.com/typelevel/cats/pull/3291"
+  private val sha1 = Sha1(HexString.unsafeFrom("a2ced5793c2832ada8c14ba5c77e51c4bc9656a8"))
+  private val number = PullRequestNumber(3291)
+
+  test("createOrUpdate >> findPullRequest >> lastPullRequestCreatedAt") {
+    val repo = Repo("pr-repo-test", "repo1")
+    val update = TestData.Updates.PortableScala
+
+    val p = for {
+      _ <- pullRequestRepository.createOrUpdate(
+        repo,
+        url,
+        sha1,
+        update,
+        PullRequestState.Open,
+        number
       )
-    }
-
-    test("getObsoleteOpenPullRequests for single update") {
-      val update = TestData.Updates.PortableScala
-      val nextUpdate = TestData.Updates.PortableScala.copy(newerVersions = Nel.of("1.0.1"))
-
-      val p = for {
-        emptyResult <- pullRequestRepository.getObsoleteOpenPullRequests(repo, nextUpdate)
-        _ <- pullRequestRepository.createOrUpdate(
-          repo,
-          url,
-          sha1,
-          update,
-          PullRequestState.Open,
-          number
-        )
-        result <- pullRequestRepository.getObsoleteOpenPullRequests(repo, nextUpdate)
-        _ <- pullRequestRepository.changeState(repo, url, PullRequestState.Closed)
-        closedResult <- pullRequestRepository.getObsoleteOpenPullRequests(repo, nextUpdate)
-      } yield (emptyResult, result, closedResult)
-      val (state, (emptyResult, result, closedResult)) = p.run(MockState.empty).unsafeRunSync()
-      val store = config.workspace / "store/pull_requests/v2/typelevel/cats/pull_requests.json"
-      assertEquals(emptyResult, List.empty)
-      assertEquals(closedResult, List.empty)
-      assertEquals(result, List((number, url, TestData.Updates.PortableScala)))
-
-      checkCommands(
-        state,
-        Vector(
-          List("read", store.toString),
-          List("read", store.toString),
-          List("write", store.toString),
-          List("read", store.toString),
-          List("read", store.toString),
-          List("write", store.toString),
-          List("read", store.toString)
-        )
+      result <- pullRequestRepository.findLatestPullRequest(repo, update.crossDependency, "1.0.0")
+      createdAt <- pullRequestRepository.lastPullRequestCreatedAt(repo)
+    } yield (result, createdAt)
+    val (state, (result, createdAt)) = p.run(MockState.empty).unsafeRunSync()
+
+    val store = config.workspace / s"store/pull_requests/v2/github/${repo.show}/pull_requests.json"
+    assertEquals(result, Some((url, sha1, PullRequestState.Open)))
+    assert(createdAt.isDefined)
+
+    checkCommands(
+      state,
+      Vector(
+        List("read", store.toString),
+        List("write", store.toString)
       )
-    }
-
-    test("getObsoleteOpenPullRequests for the same single update") {
-      val update = TestData.Updates.PortableScala
-
-      val p = for {
-        emptyResult <- pullRequestRepository.getObsoleteOpenPullRequests(repo, update)
-        _ <- pullRequestRepository.createOrUpdate(
-          repo,
-          url,
-          sha1,
-          update,
-          PullRequestState.Open,
-          number
-        )
-        result <- pullRequestRepository.getObsoleteOpenPullRequests(repo, update)
-      } yield (emptyResult, result)
-      val (state, (emptyResult, result)) = p.run(MockState.empty).unsafeRunSync()
-      val store = config.workspace / "store/pull_requests/v2/typelevel/cats/pull_requests.json"
-      assertEquals(emptyResult, List.empty)
-      assertEquals(result, List.empty)
-
-      checkCommands(
-        state,
-        Vector(
-          List("read", store.toString),
-          List("read", store.toString),
-          List("write", store.toString),
-          List("read", store.toString)
-        )
+    )
+  }
+
+  test("getObsoleteOpenPullRequests for single update") {
+    val repo = Repo("pr-repo-test", "repo2")
+    val update = TestData.Updates.PortableScala
+    val nextUpdate = TestData.Updates.PortableScala.copy(newerVersions = Nel.of("1.0.1"))
+
+    val p = for {
+      emptyResult <- pullRequestRepository.getObsoleteOpenPullRequests(repo, nextUpdate)
+      _ <- pullRequestRepository.createOrUpdate(
+        repo,
+        url,
+        sha1,
+        update,
+        PullRequestState.Open,
+        number
       )
-    }
-
-    test("getObsoleteOpenPullRequests for the another single update and ignore closed") {
-      val updateInStore = TestData.Updates.PortableScala
-      val newUpdate = TestData.Updates.CatsCore
-
-      val p = for {
-        emptyResult <- pullRequestRepository.getObsoleteOpenPullRequests(repo, updateInStore)
-        _ <- pullRequestRepository.createOrUpdate(
-          repo,
-          url,
-          sha1,
-          updateInStore,
-          PullRequestState.Open,
-          number
-        )
-        result <- pullRequestRepository.getObsoleteOpenPullRequests(repo, newUpdate)
-      } yield (emptyResult, result)
-      val (state, (emptyResult, result)) = p.run(MockState.empty).unsafeRunSync()
-      val store = config.workspace / "store/pull_requests/v2/typelevel/cats/pull_requests.json"
-      assertEquals(emptyResult, List.empty)
-      assertEquals(result, List.empty)
-
-      checkCommands(
-        state,
-        Vector(
-          List("read", store.toString),
-          List("read", store.toString),
-          List("write", store.toString),
-          List("read", store.toString)
-        )
+      result <- pullRequestRepository.getObsoleteOpenPullRequests(repo, nextUpdate)
+      _ <- pullRequestRepository.changeState(repo, url, PullRequestState.Closed)
+      closedResult <- pullRequestRepository.getObsoleteOpenPullRequests(repo, nextUpdate)
+    } yield (emptyResult, result, closedResult)
+    val (state, (emptyResult, result, closedResult)) = p.run(MockState.empty).unsafeRunSync()
+    val store = config.workspace / s"store/pull_requests/v2/github/${repo.show}/pull_requests.json"
+    assertEquals(emptyResult, List.empty)
+    assertEquals(closedResult, List.empty)
+    assertEquals(result, List((number, url, TestData.Updates.PortableScala)))
+
+    checkCommands(
+      state,
+      Vector(
+        List("read", store.toString),
+        List("write", store.toString),
+        List("write", store.toString)
       )
-    }
+    )
   }
 
-  private def withStoreData(f: (Repo, Uri, Sha1, PullRequestNumber) => Unit): Unit = {
-    val repo = Repo("typelevel", "cats")
-    val url = uri"https://github.com/typelevel/cats/pull/3291"
-    val sha1 = Sha1(HexString.unsafeFrom("a2ced5793c2832ada8c14ba5c77e51c4bc9656a8"))
-    val number = PullRequestNumber(3291)
+  test("getObsoleteOpenPullRequests for the same single update") {
+    val repo = Repo("pr-repo-test", "repo3")
+    val update = TestData.Updates.PortableScala
+
+    val p = for {
+      emptyResult <- pullRequestRepository.getObsoleteOpenPullRequests(repo, update)
+      _ <- pullRequestRepository.createOrUpdate(
+        repo,
+        url,
+        sha1,
+        update,
+        PullRequestState.Open,
+        number
+      )
+      result <- pullRequestRepository.getObsoleteOpenPullRequests(repo, update)
+    } yield (emptyResult, result)
+    val (state, (emptyResult, result)) = p.run(MockState.empty).unsafeRunSync()
+    val store = config.workspace / s"store/pull_requests/v2/github/${repo.show}/pull_requests.json"
+    assertEquals(emptyResult, List.empty)
+    assertEquals(result, List.empty)
+
+    checkCommands(
+      state,
+      Vector(
+        List("read", store.toString),
+        List("write", store.toString)
+      )
+    )
+  }
 
-    f(repo, url, sha1, number)
+  test("getObsoleteOpenPullRequests for the another single update and ignore closed") {
+    val repo = Repo("pr-repo-test", "repo4")
+    val updateInStore = TestData.Updates.PortableScala
+    val newUpdate = TestData.Updates.CatsCore
+
+    val p = for {
+      emptyResult <- pullRequestRepository.getObsoleteOpenPullRequests(repo, updateInStore)
+      _ <- pullRequestRepository.createOrUpdate(
+        repo,
+        url,
+        sha1,
+        updateInStore,
+        PullRequestState.Open,
+        number
+      )
+      result <- pullRequestRepository.getObsoleteOpenPullRequests(repo, newUpdate)
+    } yield (emptyResult, result)
+    val (state, (emptyResult, result)) = p.run(MockState.empty).unsafeRunSync()
+    val store = config.workspace / s"store/pull_requests/v2/github/${repo.show}/pull_requests.json"
+    assertEquals(emptyResult, List.empty)
+    assertEquals(result, List.empty)
+
+    checkCommands(
+      state,
+      Vector(
+        List("read", store.toString),
+        List("write", store.toString)
+      )
+    )
   }
 }
 
diff --git a/modules/core/src/test/scala/org/scalasteward/core/persistence/JsonKeyValueStoreTest.scala b/modules/core/src/test/scala/org/scalasteward/core/persistence/JsonKeyValueStoreTest.scala
index 4990d2d6..9e2bec5f 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/persistence/JsonKeyValueStoreTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/persistence/JsonKeyValueStoreTest.scala
@@ -2,7 +2,8 @@ package org.scalasteward.core.persistence
 
 import cats.syntax.all._
 import munit.FunSuite
-import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.config
+import org.scalasteward.core.mock.MockContext.context._
 import org.scalasteward.core.mock.{MockEff, MockState}
 
 class JsonKeyValueStoreTest extends FunSuite {
diff --git a/modules/core/src/test/scala/org/scalasteward/core/repoconfig/RepoConfigAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/repoconfig/RepoConfigAlgTest.scala
index 1262d9d2..70be5b2e 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/repoconfig/RepoConfigAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/repoconfig/RepoConfigAlgTest.scala
@@ -5,7 +5,7 @@ import eu.timepit.refined.types.numeric.NonNegInt
 import munit.FunSuite
 import org.scalasteward.core.TestSyntax._
 import org.scalasteward.core.data.{GroupId, Update}
-import org.scalasteward.core.mock.MockContext.repoConfigAlg
+import org.scalasteward.core.mock.MockContext.context.repoConfigAlg
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.util.Nel
 import org.scalasteward.core.vcs.data.Repo
diff --git a/modules/core/src/test/scala/org/scalasteward/core/scalafix/MigrationAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/scalafix/MigrationAlgTest.scala
index cbfbc6ed..bb8b7e84 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/scalafix/MigrationAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/scalafix/MigrationAlgTest.scala
@@ -3,7 +3,7 @@ package org.scalasteward.core.scalafix
 import munit.FunSuite
 import org.scalasteward.core.TestSyntax._
 import org.scalasteward.core.data.{GroupId, Update, Version}
-import org.scalasteward.core.mock.MockContext.migrationAlg
+import org.scalasteward.core.mock.MockContext.context.migrationAlg
 import org.scalasteward.core.util.Nel
 
 class MigrationAlgTest extends FunSuite {
diff --git a/modules/core/src/test/scala/org/scalasteward/core/scalafix/MigrationsLoaderTest.scala b/modules/core/src/test/scala/org/scalasteward/core/scalafix/MigrationsLoaderTest.scala
index e4f5b576..60bf56cf 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/scalafix/MigrationsLoaderTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/scalafix/MigrationsLoaderTest.scala
@@ -5,7 +5,7 @@ import org.http4s.Uri
 import org.scalasteward.core.application.Config.ScalafixCfg
 import org.scalasteward.core.data.{GroupId, Version}
 import org.scalasteward.core.io.FileAlgTest.ioFileAlg
-import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.context.migrationsLoader
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.scalafix.MigrationsLoaderTest.mockState
 import org.scalasteward.core.util.Nel
diff --git a/modules/core/src/test/scala/org/scalasteward/core/scalafmt/ScalafmtAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/scalafmt/ScalafmtAlgTest.scala
index 1a5f50bf..2187032a 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/scalafmt/ScalafmtAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/scalafmt/ScalafmtAlgTest.scala
@@ -3,6 +3,7 @@ package org.scalasteward.core.scalafmt
 import munit.FunSuite
 import org.scalasteward.core.data.Version
 import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.context.scalafmtAlg
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.vcs.data.{BuildRoot, Repo}
 
diff --git a/modules/core/src/test/scala/org/scalasteward/core/update/ArtifactMigrationsTest.scala b/modules/core/src/test/scala/org/scalasteward/core/update/ArtifactMigrationsTest.scala
index 34127684..0ddb9969 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/update/ArtifactMigrationsTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/update/ArtifactMigrationsTest.scala
@@ -3,7 +3,7 @@ package org.scalasteward.core.update
 import munit.FunSuite
 import org.scalasteward.core.TestSyntax._
 import org.scalasteward.core.data.{ArtifactId, GroupId, Update}
-import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.context.updateAlg
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.update.ArtifactMigrations.ArtifactChange
 import org.scalasteward.core.util.Nel
diff --git a/modules/core/src/test/scala/org/scalasteward/core/update/FilterAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/update/FilterAlgTest.scala
index efb4d5b9..533fca5e 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/update/FilterAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/update/FilterAlgTest.scala
@@ -4,7 +4,7 @@ import munit.FunSuite
 import org.scalasteward.core.TestSyntax._
 import org.scalasteward.core.data.Update.Single
 import org.scalasteward.core.data.{ArtifactId, Dependency, GroupId}
-import org.scalasteward.core.mock.MockContext.filterAlg
+import org.scalasteward.core.mock.MockContext.context.filterAlg
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.repoconfig.{RepoConfig, UpdatePattern, UpdatesConfig}
 import org.scalasteward.core.update.FilterAlg._
diff --git a/modules/core/src/test/scala/org/scalasteward/core/update/PruningAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/update/PruningAlgTest.scala
index 07f6e983..dbe30c41 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/update/PruningAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/update/PruningAlgTest.scala
@@ -4,6 +4,7 @@ import io.circe.parser.decode
 import munit.FunSuite
 import org.scalasteward.core.data.RepoData
 import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.context.pruningAlg
 import org.scalasteward.core.mock.MockState
 import org.scalasteward.core.repocache.RepoCache
 import org.scalasteward.core.repoconfig.RepoConfig
@@ -24,7 +25,7 @@ class PruningAlgTest extends FunSuite {
           |}""".stripMargin
     )
     val pullRequestsFile =
-      config.workspace / "store/pull_requests/v2/fthomas/scalafix-test/pull_requests.json"
+      config.workspace / "store/pull_requests/v2/github/fthomas/scalafix-test/pull_requests.json"
     val pullRequestsContent =
       s"""|{
           |  "https://github.com/fthomas/scalafix-test/pull/27" : {
@@ -70,7 +71,7 @@ class PruningAlgTest extends FunSuite {
   }
 
   test("needsAttention: 0 updates when includeScala not specified in repo config") {
-    val repo = Repo("fthomas", "scalafix-test")
+    val repo = Repo("pruning-test", "repo2")
     val Right(repoCache) = decode[RepoCache](
       s"""|{
           |  "sha1": "12def27a837ba6dc9e17406cbbe342fba3527c14",
@@ -112,10 +113,10 @@ class PruningAlgTest extends FunSuite {
           |}""".stripMargin
     )
     val pullRequestsFile =
-      config.workspace / "store/pull_requests/v2/fthomas/scalafix-test/pull_requests.json"
+      config.workspace / s"store/pull_requests/v2/github/${repo.show}/pull_requests.json"
     val pullRequestsContent =
       s"""|{
-          |  "https://github.com/fthomas/scalafix-test/pull/27" : {
+          |  "https://github.com/${repo.show}/pull/27" : {
           |    "baseSha1" : "12def27a837ba6dc9e17406cbbe342fba3527c14",
           |    "update" : {
           |      "Single" : {
@@ -143,7 +144,7 @@ class PruningAlgTest extends FunSuite {
           |  }
           |}""".stripMargin
     val versionsFile =
-      config.workspace / "store/versions/v1/https/foobar.org/maven2/org/scala-lang/scala-library/versions.json"
+      config.workspace / "store/versions/v2/https/foobar.org/maven2/org/scala-lang/scala-library/versions.json"
     val versionsContent =
       s"""|{
           |  "updatedAt" : 9999999999999,
@@ -164,16 +165,16 @@ class PruningAlgTest extends FunSuite {
     val expected = initial.copy(
       commands = Vector(List("read", pullRequestsFile.toString)),
       logs = Vector(
-        (None, "Find updates for fthomas/scalafix-test"),
+        (None, s"Find updates for ${repo.show}"),
         (None, "Found 0 updates"),
-        (None, "fthomas/scalafix-test is up-to-date")
+        (None, s"${repo.show} is up-to-date")
       )
     )
     assertEquals(state, expected)
   }
 
   test("needsAttention: update scala-library when includeScala=true in repo config") {
-    val repo = Repo("fthomas", "scalafix-test")
+    val repo = Repo("pruning-test", "repo3")
     val Right(repoCache) = decode[RepoCache](
       s"""|{
           |  "sha1": "12def27a837ba6dc9e17406cbbe342fba3527c14",
@@ -208,27 +209,17 @@ class PruningAlgTest extends FunSuite {
           |    }
           |  ],
           |  "maybeRepoConfig": {
-          |    "pullRequests": {
-          |      "frequency": "@daily"
-          |    },
           |    "updates" : {
-          |      "pin" : [
-          |      ],
-          |      "allow" : [
-          |      ],
-          |      "ignore" : [
-          |      ],
-          |      "limit" : null,
           |      "includeScala" : true
           |    }
           |  }
           |}""".stripMargin
     )
     val pullRequestsFile =
-      config.workspace / "store/pull_requests/v2/fthomas/scalafix-test/pull_requests.json"
+      config.workspace / s"store/pull_requests/v2/github/${repo.show}/pull_requests.json"
     val pullRequestsContent =
       s"""|{
-          |  "https://github.com/fthomas/scalafix-test/pull/27" : {
+          |  "https://github.com/${repo.show}/pull/27" : {
           |    "baseSha1" : "12def27a837ba6dc9e17406cbbe342fba3527c14",
           |    "update" : {
           |      "Single" : {
@@ -256,7 +247,7 @@ class PruningAlgTest extends FunSuite {
           |  }
           |}""".stripMargin
     val versionsFile =
-      config.workspace / "store/versions/v1/https/foobar.org/maven2/org/scala-lang/scala-library/versions.json"
+      config.workspace / "store/versions/v2/https/foobar.org/maven2/org/scala-lang/scala-library/versions.json"
     val versionsContent =
       s"""|{
           |  "updatedAt" : 9999999999999,
@@ -278,16 +269,14 @@ class PruningAlgTest extends FunSuite {
       commands = Vector(
         List("read", versionsFile.toString),
         List("read", pullRequestsFile.toString),
-        List("read", versionsFile.toString),
-        List("read", pullRequestsFile.toString),
-        List("read", pullRequestsFile.toString)
+        List("read", versionsFile.toString)
       ),
       logs = Vector(
-        (None, "Find updates for fthomas/scalafix-test"),
+        (None, s"Find updates for ${repo.show}"),
         (None, "Found 1 update:\n  org.scala-lang:scala-library : 2.12.10 -> 2.12.11"),
         (
           None,
-          "fthomas/scalafix-test is outdated:\n  new version: org.scala-lang:scala-library : 2.12.10 -> 2.12.11"
+          s"${repo.show} is outdated:\n  new version: org.scala-lang:scala-library : 2.12.10 -> 2.12.11"
         )
       )
     )
diff --git a/modules/core/src/test/scala/org/scalasteward/core/util/loggerTest.scala b/modules/core/src/test/scala/org/scalasteward/core/util/loggerTest.scala
index eccf1767..2a0b088d 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/util/loggerTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/util/loggerTest.scala
@@ -2,7 +2,7 @@ package org.scalasteward.core.util
 
 import cats.{Applicative, ApplicativeThrow}
 import munit.FunSuite
-import org.scalasteward.core.mock.MockContext._
+import org.scalasteward.core.mock.MockContext.context._
 import org.scalasteward.core.mock.{MockEff, MockState}
 import org.scalasteward.core.util.logger.LoggerOps
 
@@ -10,7 +10,7 @@ class loggerTest extends FunSuite {
   test("attemptLog") {
     final case class Err(msg: String) extends Throwable(msg)
     val err = Err("hmm?")
-    val state = mockLogger
+    val state = logger
       .attemptLogLabel("run")(ApplicativeThrow[MockEff].raiseError(err))
       .runS(MockState.empty)
       .unsafeRunSync()
@@ -18,15 +18,15 @@ class loggerTest extends FunSuite {
   }
 
   test("infoTimed") {
-    val state = mockLogger
-      .infoTimed(_ => "timed")(mockLogger.info("inner"))
+    val state = logger
+      .infoTimed(_ => "timed")(logger.info("inner"))
       .runS(MockState.empty)
       .unsafeRunSync()
     assertEquals(state.logs, Vector((None, "inner"), (None, "timed")))
   }
 
   test("infoTotalTime") {
-    val state = mockLogger
+    val state = logger
       .infoTotalTime("run")(Applicative[MockEff].unit)
       .runS(MockState.empty)
       .unsafeRunSync()
diff --git a/modules/core/src/test/scala/org/scalasteward/core/vcs/VCSRepoAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/vcs/VCSRepoAlgTest.scala
index 29fc54a8..4833fa95 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/vcs/VCSRepoAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/vcs/VCSRepoAlgTest.scala
@@ -3,7 +3,8 @@ package org.scalasteward.core.vcs
 import munit.FunSuite
 import org.http4s.syntax.literals._
 import org.scalasteward.core.git.Branch
-import org.scalasteward.core.mock.MockContext.{config, envVars, gitAlg, mockLogger, vcsRepoAlg}
+import org.scalasteward.core.mock.MockContext.context.{gitAlg, logger, vcsRepoAlg}
+import org.scalasteward.core.mock.MockContext.{config, envVars}
 import org.scalasteward.core.mock.{MockContext, MockEff, MockState}
 import org.scalasteward.core.vcs.data.{Repo, RepoOut, UserOut}