不久前,我从akka-http切换到http4s。我想要正确执行的基本操作之一-JSON处理,尤其是发送JSON响应。
我决定在ZIO中使用http4s而不是cat,因此这是http路由的样子:
import fs2.Stream
import org.http4s._
import org.http4s.dsl.io._
import org.http4s.implicits._
import scalaz.zio.Task
import scalaz.zio.interop.catz._
import io.circe.generic.auto._
import io.circe.syntax._
class TweetsRoutes {
case class Tweet(author: String, tweet: String)
val helloWorldService = HttpRoutes.of[Task] {
case GET -> Root / "hello" / name => Task {
Response[Task](Ok)
.withBodyStream(Stream.emits(
Tweet(name, "dummy tweet text").asJson.toString.getBytes
))
}
}.orNotFound
}
Run Code Online (Sandbox Code Playgroud)
如您所见,JSON序列化部分非常冗长:
.withBodyStream(Stream.emits(
Tweet(name, "dummy tweet text").asJson.toString.getBytes
))
Run Code Online (Sandbox Code Playgroud)
还有其他方法可以在响应中发送JSON吗?
我有以下功能,我想测试:
def people(id: Int): RIO[R, People]
Run Code Online (Sandbox Code Playgroud)
如果有一个,这个函数会返回 People id,resp。如果不是,则失败,例如:
IO.fail(ServiceException(s"No People with id $id"))
Run Code Online (Sandbox Code Playgroud)
快乐的案例有效,例如:
suite("Get a Person for an ID") (
testM("get Luke Skywalker") {
for {
peopleRef <- Ref.make(Vector(People()))
luke <- Swapi.>.people(1).provide(Test(peopleRef))
} yield assert(luke, equalTo(People()))
},
Run Code Online (Sandbox Code Playgroud)
但是我如何测试失败案例呢?我尝试了不同的东西,主要是类型不匹配。这是一个尝试:
testM("get not existing People") {
(for {
peopleRef <- Ref.make(Vector(People()))
failure = Swapi.>.people(2).provide(Test(peopleRef))
} yield assertM(failure, fail(Cause.die(ServiceException(s"No People with id 2")))
}
)
Run Code Online (Sandbox Code Playgroud) I could not find anything on how to ignore a Suite or a Test with ZIO Test.
Whether in an example nor in the documentation (https://zio.dev/docs/usecases/usecases_testing)
There is an ignored in the test package object:
/**
* Creates an ignored test result.
*/
final val ignored: ZTest[Any, Nothing, Nothing] =
ZIO.succeed(TestSuccess.Ignored)
Run Code Online (Sandbox Code Playgroud)
But how can it be used in your code?
I tried different things, but with no success.
这可能是一个愚蠢的问题,但从 ZIO 开始,我无法设法将 a 转换Seq[ZIO]为ZIO[Seq]:
def translate(keys: Seq[String], locales: Seq[Locale]):RIO[Translator, Seq[Translation]] = {
for {
service <- ZIO.environment[Translator]
} yield {
// service.translate produce a zio.Task[Translation]
keys.map(k => service.translate(k, locales)
}
}
Run Code Online (Sandbox Code Playgroud)
必需:RIO[翻译器,Seq[翻译]]
找到:ZIO[翻译器,无,Seq[zio.Task[翻译]]
我尝试过,flatMap但是flatten我无法与任何人取得预期的结果。collectAllmerge
如何将 a 转换Seq[ZIO[_, _, B]]为 a ZIO[_, _, Seq[B]]?
谢谢
编辑:这似乎ZIO.foreach是最好的选择,但是由于 for 理解,我仍然将它包裹在另一个 ZIO 中。
我有一个返回一些 ZIO 的方法:
def method(...): ZIO[Any with clock, SomeError, Unit]
Run Code Online (Sandbox Code Playgroud)
调用此返回的方法Task[Unit]:
def otherMethod(..): Task[Unit] = {
ZIO.effect(method(...))
}
Run Code Online (Sandbox Code Playgroud)
问题是当我调用它时ZIO.effect我没有得到结果。我应该如何转换ZIO,以Task获得结果呢?
我正在尝试ZIO。
我不明白为什么Live将添加为Trait,然后object提供,例如:
object Live extends Live
Run Code Online (Sandbox Code Playgroud)
例如,可以在不同的地方找到此模式zio.console.Console。
是否有原因,或者在某些情况下有意义?
假设我有这样的代码:
final case class CustomException(errorCode: Int, id: UUID) extends Throwable
val logic: ZIO[Any, Throwable, Unit] = ???
Run Code Online (Sandbox Code Playgroud)
我想使用 ZIO Test 来检查特定的错误情况
val checkForTimeout = testM("Logic should time out") {
for {
result <- logic.flip
} yield assert(result, isSubtype[CustomException](???))
}
Run Code Online (Sandbox Code Playgroud)
我想做的是检查该errorCode字段的特定值。但 ZIO Test 中现有的组合器似乎只允许我检查完整的对象。我只想_.errorCode在忽略时检查_.id,这意味着equalTo对于这个用例来说不是一个足够好的组合器。
我该如何解决这个问题?
我有下一个代码:
import zio._
import scala.concurrent.Future
case class AppError(description: String) extends Throwable
// legacy-code imitation
def method(x: Int): Task[Boolean] = {
Task.fromFuture { implicit ec => Future.successful(x == 0) }
}
def handler(input: Int): IO[AppError, Int] = {
for {
result <- method(input)
_ <- IO.fail(AppError("app error")).when(result)
} yield input
}
Run Code Online (Sandbox Code Playgroud)
但这段代码无法编译,因为编译器说结果类型是:
ZIO[Any, Throwable, Int]
如何从Task(我调用的地方method)转换为IO?
ZIO( https://zio.dev/ ) 是一个 Scala 框架,其核心是数据ZIO[R, E, A]结构,其站点提供了以下三个参数的信息:
齐奥
的
ZIO[R, E, A]数据类型有三种类型的参数:
R- 环境类型。该效果需要类型为 的环境R。如果该类型参数为Any,则表示效果没有要求,因为您可以使用任何值(例如,单位值())运行效果。E- 故障类型。如果值为 type ,则效果可能会失败E。一些应用程序将使用Throwable. 如果此类型参数为Nothing,则表示效果不会失败,因为没有 Nothing 类型的值。A- 成功类型。使用 type 值可能会成功A。如果此类型参数为Unit,则表示该效果不会产生有用的信息,如果是Nothing,则表示该效果将永远运行(或直到失败)。
很容易得到什么A是:它是函数在名义情况下返回的值,即我们为函数编码的原因。
R是一种依赖注入 - 一个有趣的话题,但我们可以ZIO通过始终将其设置为Any(并且实际上IO[E, A] = ZIO[Any, E, A]在 lib 中有一个别名)来忽略它以使用它。
因此,它仍然E是用于错误的类型(著名的错误通道)。我粗略地认为这IO[E, A] …
我有一个简单的理解代码:
def nameFormatter(request: SomeRequest) : FormattedData = {
for {
config <- ZIO.fromOption(configuration.get(request.name)).orElseFail( new Exception("Unknown config"))
name = config.data.name.pipe(SomeName)
} yield FormattedData(
name,
request.age
)
}
Run Code Online (Sandbox Code Playgroud)
但这个方法返回:
ZIO[Any, Exception, FormattedData]
Run Code Online (Sandbox Code Playgroud)
我想更改此方法以仅返回FormattedData,而不是整个 ZIO。是否可以?或者也许我应该以某种方式读取返回的类型并从中获取值?