2016-10-31 17 views
1

をシミュレート:私は(私は質問の目的のために簡略化されました)次のコードを持っているユーザープロンプトを作成し、相互作用

def openFile(directory: File): Try[String] = { 
     var input = "" 
     do { 
     input = readLine("prompt>") 
     println("alibaba.txt: 100%") 
     } while(input != ":quit") 
    } 

ワークフローはこれです:

ユーザーがプロンプトを取得します。

prompt>

ユーザーがalibaba書き込み、その後、プレスは

012を入力します。

ユーザーが見ている:

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%]" 

は、どのように私は、テストを行うことができますユーザーとのやり取りをシミュレートしますか?

私のプログラムが書いたものをどのように読むことができますか?

+0

万が一、あなたが答えを受け入れるだろうか? – tkachuko

答えて

1

IMOより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は、出力元を表します。場合

    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使用することができ、より制御したい:この場合

    をデフォルトでは、ユーザーがすぐに":quit"に入ったときのシナリオをテストしてみましょう

    System.out

です 模擬inoutにする必要があります。

ソースの期待を設定
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%") 
    } 
    } 
} 
関連する問題