2017-02-26 3 views
2

私は、スキャナオブジェクトとユーザによるキーボードからの動的入力を使用するメソッドをテストしようとしています。私はそれをテストする方法を理解できませんでした。私が使用したいメソッドは別のメソッドのループでも使用されています。私はMockitoがこの特定の状況で便利になると思います、残念ながら、私はそれをテストする方法を見つけることができませんでした。その特定のメソッドが例外をスローする間違った値を返そうとしている場合さて、コードはより深い説明を提供します(私は願っています)。JAVA JUnitテストスキャナ/ダイナミック入力

/** 
* This method asks user to insert cash 
* It gets the property text from properties file by key insert.cash 
* Checks if coin is in proper format 
* Checks if coin exists in available coins array 
* Otherwise throws exception 
* @throws InvalidCoinException 
* @return cash - how much money user inserted 
*/ 
@Override 
public double insertCash() throws InvalidCoinException { 
    double cash = 0; 
    double temp; // temporary variable which goes through all if statems if all conditions are satisfied it gets assigned to cash variable 
    boolean coinExists = false; 
    System.out.println(prop.getProperty("insert.cash")); 

    if(!sc.hasNextDouble()) { 
     throw new InvalidCoinException(MessageFormat.format(prop.getProperty("invalid.coin"), sc.next())); 
    } 

    else { 

     temp = sc.nextDouble(); 

     for(int i = 0; i < availableCoins.length; i++) { 
      if(temp == availableCoins[i] || temp == 0) { 
       coinExists = true; 
      } 
     } 


     if(coinExists == true) { 
      cash = temp; 
     } 

     else { 
      throw new InvalidCoinException(MessageFormat.format(prop.getProperty("invalid.coin"), temp)); 
     } 

    } 

    return cash; 

} 

JUNIT:(だけではなく、一つの方法は、スキャナを使用しているため)

@org.junit.Before 
public void initializeTest() throws IOException { 
    machine = new CoffeeMachineImplementation(); 
    machineSpy = Mockito.spy(CoffeeMachineImplementation.class); 
} 

@org.junit.Test 
public void testInsertCash() throws InvalidCoinException { 
    System.out.println("---------------- Insert cash -----------------"); 

    Double input2 = 0.06; 
    Double input3 = 200.0; 
    Double input4 = 0.02; 



    try { 
     when(machineSpy.insertCash()).thenReturn(input2) 
            .thenThrow(new InvalidCoinException("...")); 
     fail("Should have thrown an exception " + input2); 
    } 

    catch (InvalidCoinException e) { 
     String exception = "Invalid coin: " + input2 + " euro is not existing coin"; 
     System.out.println(e.getMessage()); 
     assertEquals(exception, e.getMessage()); 
    } 

が私のスキャナオブジェクトはコンストラクタで宣言されています。

public CoffeeMachineImplementation() throws IOException { 
     prop = new Properties(); 
     input = new FileInputStream("src/localization.properties"); 
     maWaterCap = 5; 
     maCoffeeCap = 3; 
     prop.load(input); 
     sc = new Scanner(System.in); 
    } 

答えて

1

その場合にはポイントはないように思えます。 ..

次のようにクラスを変更します:

A)スキャナモック注射を

Bを有効にするために)、任意の外部リソース

Implをクラス

public CoffeeMachineImplementation() throws IOException { 
     maWaterCap = 5; 
     maCoffeeCap = 3; 

     setScannerInstance(new Scanner(System.in)); 
    } 

void setScannerInstance(Scanner s){ 
    this.sc = sc; 
} 

String getExceptionMessage(String propKey, Double value){ 
    return MessageFormat.format(prop.getProperty(propKey), value); 
} 

Properties getProperties(){ 
    if(prop == null){ 
     prop = new Properties(); 
     input = new FileInputStream("src/localization.properties"); 
     prop.load(input); 
    } 

    return prop; 
} 


public double insertCash() throws InvalidCoinException { 
    double cash = 0; 
    double temp; // temporary variable which goes through all if statems if all conditions are satisfied it gets assigned to cash variable 
    boolean coinExists = false; 
    System.out.println(getProperties().getProperty("insert.cash")); 

    if(!sc.hasNextDouble()) { 
     throw new InvalidCoinException(getExceptionMessage("invalid.coin", sc.next())); 
    } 

テストクラス

を呼び出す回避するために、例外メッセージの作成をモックスキャナは最終クラスです。PowerMockitoは、一番下の行は、あなたが...さまざまなテスト状況でスキャナクラスをモックして、通常insertCash()を起動しようとすると、特定の行動を期待するべきであるということです(example

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Scanner.class) 
class CoffeeMachineImplementationTest{ 

@org.junit.Before 
public void initializeTest() throws IOException { 
    machine = new CoffeeMachineImplementation(); 
    machineSpy = Mockito.spy(CoffeeMachineImplementation.class); 
    doReturn(new Properties()).when(machineSpy).getProperties(); 
} 

@org.junit.Test 
public void shouldThrowException_whenNoNextDouble() throws InvalidCoinException { 

    Double input = 0.06; 
    String expectedMessage = "expectedMessage"; 

    Scanner scMock = PowerMock.createMock(Scanner.class) 
    machineSpy.setScannerInstance(scMock); 

    when(scMock.hasNextDouble()).thenReturn(false); 
    when(scMock.next()).thenReturn(input); 

    doReturn(expectedMessage).when(machineSpy) 
     .getExceptionMessage("invalid.coin", input); 

    try { 
     machineSpy.insertCash(); 
    } 

    catch (InvalidCoinException e) { 
     assertEquals(expectedMessage, e.getMessage()); 
    } 

を使用する必要があります。

+0

私はgettin nullポインタ例外です – user2204367

+0

私はそのコンストラクタでロードされているプロパティについて疑問に思っています..私の更新をチェックしてください –

+0

よく修正しました。とにかく助けてくれてありがとう。ほとんどそれは、その方法について多くの助けとなったスキャナセッター注入についてでした:) – user2204367