我有以下代码(为了这个问题我已经简化了):
def openFile(directory: File): Try[String] = {
var input = ""
do {
input = readLine("prompt>")
println("alibaba.txt: 100%")
} while(input != ":quit")
}工作流程是这样的:
用户会得到一个提示:
prompt>
用户编写alibaba,然后按enter键
用户可以看到:
alibaba.txt: 100%
prompt>一切:
prompt>alibaba
alibaba.txt: 100%
prompt>现在,我想测试一下它。
我编写了以下代码来测试用户交互:
test("simulate user input from readline") {
val prompt = new Prompt()
prompt.openFile(new File("../resources"))
val in = new ByteArrayInputStream("alibaba\n".getBytes)
System.setIn(in)
val scanner: Scanner = new Scanner(System.in)
val programResponse: String = scanner.nextLine()
println("programResponse: " + programResponse)
System.setIn(System.in)
assert(programResponse == "alibaba.txt: 100%")
}然而,我得到了这个结果,我很困惑:
"alibaba[]" did not equal "alibaba[.txt: 100%]"那么,如何让测试模拟用户交互呢?
如何读取我的程序所写的内容?
发布于 2016-11-01 04:34:56
我想你应该以一种简单的可测试的方式来组织你的代码,这意味着你应该将IO提取到更高的抽象中。
出于演示目的,我将您的示例稍微修改为以下代码:
import java.util.Scanner
object YourObject {
def consoleMethod(in: () => String = new Scanner(System.in).nextLine,
out: String => Unit = System.out.println): Unit = {
var input = ""
do {
out("prompt>")
input = in()
out("alibaba.txt: 100%")
} while (input != ":quit")
}
}让我们把它分解一下
in: () => String = new Scanner(System.in).nextLine代表我们的用户输入源。默认情况下,它是System.in.out: String => Unit = System.out.println代表我们的输出源。缺省情况下为System.out让我们测试一下当用户立即进入":quit"时的场景:
import org.scalatest.{Matchers, WordSpec}
class Test extends WordSpec with Matchers {
"We" should {
"simulate user input from readline" in {
var outputs = List.empty[String]
def accumulate(output: String): Unit = outputs = outputs :+ output
val in: () => String = () => ":quit"
val out: String => Unit = accumulate _
YourObject.consoleMethod(in, out)
outputs shouldBe List("prompt>", "alibaba.txt: 100%")
}
}
}如果您想要更多的控制,可以使用scalamock
在这种情况下,我们可以模拟、in和out,让它们按照我们需要的方式运行。
val in = mock[() => String]
val out = mock[String => Unit]设置来源预期:
(in.apply _).expects().anyNumberOfTimes().onCall(_ => ":quit")现在我们想要设置out来记录我们将要写入的内容:
var outputs = List.empty[String]
def accumulate(output: String): Unit = outputs = outputs :+ output
(out.apply _)
.expects(new FunctionAdapter1[String, Boolean](_ => true))
.anyNumberOfTimes()
.onCall(accumulate _)太好了,现在让我们设置一下期望:
outputs shouldBe List("prompt>", "alibaba.txt: 100%")的全部源代码的测试
import org.scalamock.function.FunctionAdapter1
import org.scalamock.scalatest.MockFactory
import org.scalatest.{Matchers, WordSpec}
class Test extends WordSpec with Matchers with MockFactory {
"We" should {
"simulate user input from readline" in {
val in = mock[() => String]
val out = mock[String => Unit]
(in.apply _).expects().anyNumberOfTimes().onCall(_ => ":quit")
var outputs = List.empty[String]
def accumulate(output: String): Unit = outputs = outputs :+ output
(out.apply _)
.expects(new FunctionAdapter1[String, Boolean](_ => true))
.anyNumberOfTimes()
.onCall(accumulate _)
YourObject.consoleMethod(in, out)
outputs shouldBe List("prompt>", "alibaba.txt: 100%")
}
}
}https://stackoverflow.com/questions/40344117
复制相似问题