JAVA JUnit测试扫描仪/动态输入

时间:2017-02-26 11:05:41

标签: java unit-testing junit mockito

我正在尝试测试我的方法,该方法使用扫描仪对象和用户键盘的动态输入。我无法想出一种方法来测试它。问题是我想要使用的方法也用在另一个方法的循环中。我认为Mockito在这种特殊情况下会派上用场,不幸的是,我找不到如何测试它的方法。如果该特定方法试图返回错误的值,则会抛出异常。那么,代码将提供更深入的解释(我希望)。

/**
 * 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 个答案:

答案 0 :(得分:1)

在这种情况下似乎没有意义......

我会更改类如下:

a)启用扫描仪模拟注入

b)模拟异常消息创建以避免调用任何外部资源

Impl Class

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 应该使用(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());
    }

最重要的是,您应该尝试在各种测试情况下模拟扫描器类,然后正常调用insertCash() ..并期望某些行为。