Практически в любой тестовой среде вы можете сделать это, вызвав это синхронно
// given
val env: Environment[IO] = ...
val connector: DbConnector[IO] = DbConnector.impl[OP](env)
val url: DbUrl = ...
val user: DbUser = ...
val pw: DbPw = ...
// when
val result = connector.read(url, user, pw).attempt.unsafeRunSync
// then
val expected: DbParams = ...
assert(result == Right(expected))
Поскольку MUnit также изначально поддерживает Future, вы также можете сделать это так:
// given
val env: Environment[IO] = ...
val connector: DbConnector[IO] = DbConnector.impl[OP](env)
val url: DbUrl = ...
val user: DbUser = ...
val pw: DbPw = ...
// when
connector.read(url, user, pw).attempt.unsafeToFuture.map { result =>
// then
val expected: DbParams = ...
assert(result == Right(expected))
}
Факт наличие F
дает вам возможность выбрать наиболее простую для тестирования реализацию для каждого теста: cats.effect.IO
, cats.effect.SyncIO
, monix.eval.Task
, et c. И разные тестовые среды различаются только тем, как вы организуете свои тесты в наборах, какие сопоставители вы можете использовать, а иногда и с доступными интеграциями, но вы можете видеть, что можете писать тесты даже без интеграций. реализация, если ваша алгебра имеет вывод, зависящий только от ввода, и который будет следовать некоторым контрактам, вы можете определить l aws для него
class DbConnectorLaws[F[_]: MonadError[*[_], Throwable](
connector: DbConnector[F]
) {
// explicitly expressed contracts that tested class should fulfill
private def expectedReadOuput(dbUrl: DbUrl, user: DbUser, pw: DbPw) = ...
def nameOfReadContract(dbUrl: DbUrl, user: DbUser, pw: DbPw): F[Unit] =
connector.read(dbUrl, user, pw).map { result =>
// Cats laws has some utilities for making it prettier
assert(result == expectedReadOuput(dbUrl, user, pw))
}
}
, а затем вы можете протестировать его, например, с помощью Scalacheck
import org.scalacheck.Arbitrary
import org.scalacheck.Prop.forAll
// actual test with laws (cats call them discipline)
trait DbConnectorTests {
val laws: DbConnectorLaws[IO] // simplified, study cats laws if you need it
def readContract()(
implicit
dbUrls: Arbitrary[DbUrl]
users: Arbitrary[DbUser]
pws: Arbitrary[DbPw]
// also other implicits if necessary
) = {
implicit val input = for {
url <- dbUrls
user <- users
pw <- pws
} yield (url, user, pw)
// simplified as well
forall { case (url: DbUrl, user: DbUser, pw: DbPw) =>
laws.nameOfReadContract(url, user, pw).unsafeRunSync // throws if assertion fail
}
}
}
val test = new DbConnectorTests { val laws = new DbConnectorLaws[IO](implementation) }
test.readContract()
Однако кажется, что ваш интерфейс зависит от реализации и сам по себе не предоставляет никаких контрактов, которые можно было бы протестировать таким образом. Я упоминаю об этом только потому, что в других вопросах вы спрашивали про «l aws».