我试图找出如何在while循环语句中的某个迭代点上打印出哪个系统。

我有这种方法:

/**
 * This method counts how much money user inserted
 * If it is not enough to buy chosen cup size it asks user to insert more
 * Otherwise it checks if user does not need the change
 * and collects money to machine based on cup size price
 * This method gets the message from properties file by key identifies
 * add.more.money - if not enough money is in machine
 * user.paid.change - if user put too much to machine
 * user.paid - if user paid the exact amount of money
 * @param constantPrice  - cup size price
 * @return countMoney - how much user put to machine
 */
@Override
public String countMoneyForCupSize(double constantPrice) {
    // constant - price depending on cup size
    String countMoney = " ";
    double sessionMoney = 0;
    boolean flag = true;

    while(flag) {
        if(constantPrice > sessionMoney) {
            System.out.println(MessageFormat.format(prop.getProperty("add.more.money"), (constantPrice-sessionMoney)));
            double insertedCash;
            try {
                insertedCash = insertCash();
                sessionMoney = sessionMoney + insertedCash;
                if(insertedCash == 0) {
                    System.out.println(MessageFormat.format(prop.getProperty("end.procedure"), sessionMoney));
                    flag = false;
                }
            } catch (InvalidCoinException e) {
                System.out.println(e.getMessage());
            }
        }

        else {

            double change = sessionMoney - constantPrice;
            String makeCoffeeText = makeCoffee();
            if(change > 0) {
                countMoney = MessageFormat.format(prop.getProperty("user.paid.change"), makeCoffeeText, sessionMoney, change);
            }
            else {
                countMoney = MessageFormat.format(prop.getProperty("user.paid"), makeCoffeeText, sessionMoney);
            }

            collectMoney(constantPrice);
            flag = false;
        }
    }
    return countMoney;
}


JUnit:

@org.junit.Rule
public final ProvideSystemProperty property1 = new ProvideSystemProperty("MoreEuro", "You need more: 0.5 euro");

@org.junit.Test
public void testCountMoneyForCupSize() {
    System.out.println("---------------- Count Money For Cup Size -----------------");
    double largePrice = 1.5;
    double mediumPrice = 1;
    double smallPrice = 0.75;

    try {
        when(machineSpy.insertCash()).thenReturn(1.0);
        assertEquals(machineSpy.countMoneyForCupSize(largePrice), System.getProperty("MoreEuro"));

    } catch (InvalidCoinException e) {
        System.out.println(e.getMessage());
    }
}


因此,我想明确指出,如果用户插入1欧元,他仍需要再插入半欧元。

最佳答案

1)when(machineSpy.insertCash()).thenReturn(1.0);

模拟被测试的公共方法调用的私有方法不一定是一件好事,因为您应该模拟依赖关系,而不是模拟被测对象的行为。如果insertCash()具有某些必须被嘲笑的特性,则您可能应该移至另一个类中。

2)关于:


  如何在迭代的某个点中断循环并检查哪个系统
  打印出来


为什么不仅仅执行break指令?

3)machineSpy.countMoneyForCupSize(largePrice);


  因此,我想明确指出,如果用户插入1欧元。他仍然需要
  多插入一半欧元


我认为您应该更改countMoneyForCupSize(double)的约定,而不是尝试测试在控制台中编写的并没有真正测试方法行为的输出。

在您的实际版本中,该方法返回格式化的String。它不应该。
逻辑和渲染任务是两件截然不同的事情。
将两种职责混合在一起违反了“单一职责”原则(改变班级的一个以上原因)。
此外,这可能会阻止您测试方法的核心逻辑

这里 :

if(change > 0) {
    countMoney = MessageFormat.format(prop.getProperty("user.paid.change"), makeCoffeeText, sessionMoney, change);
}
else {
    countMoney = MessageFormat.format(prop.getProperty("user.paid"), makeCoffeeText, sessionMoney);
}


您应该创建一个包含所有这些数据的自定义类的实例,然后返回它而不是String。

例如 :

....
CountMoney countMoney = null;
 ...
if(change > 0) {
    countMoney = new CountMoney(makeCoffeeText, sessionMoney, change);
}
else {
    countMoney = new CountMoney(makeCoffeeText, sessionMoney);
}

...
return countMoney;


然后,在调用CountMoney countMoneyForCupSize()的应用程序代码中,您可以调用执行渲染的渲染方法(位于渲染类中),例如:String renderingCountMoney(CountMoney countMoney)

这样,您的设计会更好(每个类和每个方法都有明确定义的职责),并且可以在不考虑用户文本呈现的情况下对countMoneyForCupSize()进行单元测试。

08-03 18:12