Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ScalaTest:assert阻塞语句_Scala_Concurrency_Future_Reactive Programming_Scalatest - Fatal编程技术网

ScalaTest:assert阻塞语句

ScalaTest:assert阻塞语句,scala,concurrency,future,reactive-programming,scalatest,Scala,Concurrency,Future,Reactive Programming,Scalatest,我使用了一些带有阻塞语句的代码: blocking { Thread.sleep(10*1000) } 有没有一种方法可以断言这个阻塞语句是给定的?或者换句话说:如果有人删除阻塞语句,我是否可以编写一个失败的测试 更新:如何在未来中使用时断言阻塞?尝试使用 你应该得到这样的东西: var blocked = false // flag to detect blocking val oldContext = BlockContext.current val myContext = ne

我使用了一些带有
阻塞
语句的代码:

blocking {
    Thread.sleep(10*1000)
}
有没有一种方法可以断言这个
阻塞
语句是给定的?或者换句话说:如果有人删除
阻塞
语句,我是否可以编写一个失败的测试

更新:如何在
未来
中使用时断言阻塞?

尝试使用

你应该得到这样的东西:

var blocked = false // flag to detect blocking

val oldContext = BlockContext.current
val myContext = new BlockContext {
  override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
    blocked = true
    oldContext.blockOn(thunk)
  }
}

BlockContext.withBlockContext(myContext) {
  blocking {} // block (or not) here
}

assert(blocked) // verify that blocking happened
如果您想测试包装在
未来中的代码,请更新如何使其工作(评论后续)

构建
未来
时,它的工厂方法需要显式执行代码块(函数),隐式执行执行上下文(通常为
scala.concurrent.ExecutionContext.Implicits.global

稍后的代码块将被调度到执行上下文中,并将在其中一个线程中运行

现在,如果您只是将阻塞的代码片段包装到传递给
BlockContext.withBlockContext
的代码块中,就像您在注释中建议的那样:

BlockContext.withBlockContext(myContext) {
  Future {
    blocking { Thread.sleep(100) }
  }
}
。。。这将不起作用,因为当前线程将只执行
Future
构造,传递给
Future
的实际代码将从相关执行上下文(
BlockContext.withBlockContext
在当前线程中检测
阻塞
s)在线程中执行

话虽如此,我可以建议您做以下三件事之一:

  • 不要将要测试的代码包装到将来。如果您想测试一段代码是否使用
    阻塞
    ,只需这样做。
    编写一个函数并对其进行测试,您可以将其传递给生产中的
    Future

  • 假设出于某种原因,您无法避免在测试中创建未来。在这种情况下,您必须篡改构建未来时使用的执行上下文。
    此代码示例演示了如何做到这一点(重用原始示例中的
    blocked
    myContext
    ):


  • 如果您的
    Future
    是间接创建的,例如,由于调用了您在测试中运行的其他函数,那么您必须以某种方式(可能使用依赖项注入)将模拟执行上下文拖动到创建
    Future
    的任何位置,并在那里使用它来构建它

  • 正如您所看到的,第一个选项是最简单的,如果可以,我建议您坚持使用它。

    谢谢您的提示!除非我在
    Future
    s:
    BlockContext.withBlockContext(myContext){Future{blocking{Thread.sleep(100)}}}
    中不使用
    blocking{}
    你有办法解决它吗?
    // execution context that submits everything that is passed to it to global execution context
    // it also wraps any work submited to it into block context that records blocks
    implicit val ec = new ExecutionContext {
      override def execute(runnable: Runnable): Unit = {
       ExecutionContext.Implicits.global execute new Runnable {
          override def run(): Unit = {
            BlockContext.withBlockContext(myContext) {
              runnable.run()
            }
          }
        }
      }
      override def reportFailure(t: Throwable): Unit = {
        ExecutionContext.Implicits.global.reportFailure(t)
      }
    }
    
    // this future will use execution context defined above
    val f = Future {
      blocking {} // block (or not) here
    }
    Await.ready(f, scala.concurrent.duration.Duration.Inf)
    
    assert(blocked)