我有一个简单的测试用例,它使用TestActorRef并最终验证一个方法的超时调用。下面是3个文件源的详细信息:
测试REST实用程序.scala
import play.api.http.HttpVerbs
import play.api.libs.ws.WSClient
import javax.inject.Inject
import scala.concurrent.Future
class TestRestUtility @Inject()(ws: WSClient) extends HttpVerbs {
import scala.concurrent.ExecutionContext.Implicits.global
def getHealthStatus(): Future[Int] = {
ws.url("https://www.google.com").get().map { response =>
response.status
}
}
}
测试运行状况检查执行元.scala
import akka.actor.{Actor, ActorLogging, Props}
import play.api.http.Status
import javax.inject.Inject
import scala.concurrent.Future
import scala.concurrent.duration.{DurationInt, FiniteDuration}
import scala.util.{Failure, Success}
object TestHealthCheckActor {
def props(testRestUtility: TestRestUtility): Props = {
Props(new TestHealthCheckActor(testRestUtility: TestRestUtility))
}
}
class TestHealthCheckActor @Inject()(testRestUtility: TestRestUtility)
extends Actor with ActorLogging with Status {
import context.dispatcher
val checkPeriod: FiniteDuration = 1.seconds
var apiStatus: Int = _
override def preStart(): Unit = {
context.system.scheduler.scheduleWithFixedDelay(
0.milliseconds,
checkPeriod,
self,
RefreshHealthStatus
)
}
override def receive: Receive = {
case RefreshHealthStatus =>
val health: Future[Int] = testRestUtility.getHealthStatus()
health.onComplete({
case Success(result) =>
result match {
case OK => apiStatus = Status.OK
case _ => apiStatus = Status.REQUEST_TIMEOUT
}
case Failure(e) =>
println(e)
})
}
}
测试规格等级
import akka.actor.{ActorSystem, PoisonPill}
import akka.testkit.{ImplicitSender, TestActorRef, TestKit}
import org.mockito.Mockito
import org.mockito.Mockito.{times, verify, when}
import org.scalatest
import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach}
import org.scalatest.concurrent.Eventually
import org.scalatest.matchers.should.Matchers
import org.scalatest.time.Span
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatestplus.mockito.MockitoSugar
import play.api.http.Status
import scala.concurrent.Future
class TestSpec extends TestKit(ActorSystem("HealthCheckActorSpec")) with AnyWordSpecLike with Matchers
with BeforeAndAfterEach with MockitoSugar with ImplicitSender with Eventually with BeforeAndAfterAll with Status with TestHarnessConstants {
import scala.concurrent.ExecutionContext.Implicits.global
var mockTestRestUtility: TestRestUtility = _
"HealthCheckActor" should {
"time out and call subscription api" in {
mockTestRestUtility = mock[TestRestUtility]
when(mockTestRestUtility.getHealthStatus()).thenReturn(Future(OK)).thenReturn(Future(OK)).thenReturn(Future(OK))
val healthCheckActorShortPeriod: TestActorRef[TestHealthCheckActor] = TestActorRef(TestHealthCheckActor.props(mockTestRestUtility))
eventually(timeout(Span(9, scalatest.time.Seconds)), interval(Span(1, scalatest.time.Seconds))) {
verify(mockTestRestUtility, Mockito.atLeast(3)).getHealthStatus()
}
healthCheckActorShortPeriod ! PoisonPill
}
}
}
如“scalast-core_2.12-3.2.3-sources.jar”中关于最终的描述,它在放弃之前容忍不成功的尝试,因此测试用例预期有3次调用方法**getHealthStatus()**以成功作为mock的返回值。但我得到了一个失败的测试用例,并显示以下错误消息。我不知道为什么该方法只被调用了一次:
testRestUtility.getHealthStatus();
Wanted *at least* 3 times:
-> at com.deere.isg.ingest.supporttool.testharness.TestSpec.$anonfun$new$8(TestSpec.scala:44)
But was 1 time:
-> at com.deere.isg.ingest.supporttool.testharness.TestHealthCheckActor$$anonfun$receive$1.applyOrElse(TestHealthCheckActor.scala:36)
org.mockito.exceptions.verification.TooFewActualInvocations:
testRestUtility.getHealthStatus();
Wanted *at least* 3 times:
-> at com.deere.isg.ingest.supporttool.testharness.TestSpec.$anonfun$new$8(TestSpec.scala:44)
But was 1 time:
-> at com.deere.isg.ingest.supporttool.testharness.TestHealthCheckActor$$anonfun$receive$1.applyOrElse(TestHealthCheckActor.scala:36)
1条答案
按热度按时间6g8kf2rb1#
eventually
将认为Future(OK)
成功,因为它不会抛出异常(从技术上讲,失败的Future
也不会抛出异常,除非您在eventually
中将其解包)。由于第一次调用成功,eventually
在第一次调用之后不会再进行任何尝试。