有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JUnit在else语句以字符串形式输出错误消息时测试方法

我正在开发一个处理银行交易的程序。我的取款方法从余额中减去金额,如果没有足够的资金取款,将向屏幕输出一条错误消息。错误消息是我在测试时遇到的问题

public void withdraw(double amt) {
    double bal = getBalance();
    if(bal >= amt) {
        super.setBalance(bal - amt);
        if(bal < minBalance) {
            super.setBalance(bal - amt - maintFee);
        }   
    } else {
        System.out.println("Error: Not enough funds for withdraw");
    }       
}

这些是我目前对此方法的JUnit测试。我只需要关于testdrawThree()的帮助。谢谢大家!

@Test
void testWithdrawOne() {
    Savings s = new Savings(500.00, 30.00, "111", "Andrew Green", 1000.00);
    s.withdraw(200);
    assertEquals(800.00, s.getBalance());
}

@Test
void testWithdrawTwo() {
    Savings s = new Savings(500.00, 30.00, "111", "Andrew Green", 400.00);
    s.withdraw(200.00);
    assertEquals(170.00, s.getBalance());
}

@Test
void testWithdrawThree() {
    Savings s = new Savings(500.00, 30.00, "111", "Andrew Green", 400.00);
    s.withdraw(600.00);
    //Need to check that program will output "Error: Not enough funds for withdrawal"

}

共 (2) 个答案

  1. # 1 楼答案

    有几种方法可以做到这一点:

    1. 您可以获得系统的所有权。如本answer中所述,以及评论中提到的Andrea。我不认为这是一个很好的方法,因为这意味着您将无法并行运行您的测试。out是跨JVM的共享资源
    2. 您可以重构您的代码-如果提取不成功,您的方法可能会返回错误?您基本上是在接受错误,而不是报告它
    3. 您可以测试在没有足够资金的情况下调用该方法后余额是否没有变化。我认为这实际上是您想要测试的系统的有趣行为,不是吗?测试打印的错误消息似乎很肤浅。也许它会让你覆盖那一行代码,但这真的是你想在测试中捕捉的意思吗?是否有人真的要查看生产中的输出流并查找此消息?这又是重构代码的另一个参数

    另外,还有一个旁注:用有意义的名称来命名测试方法将大有帮助,例如testWithdrawWithoutFunds,而不是泛型名称testOnetestTwo,等等

  2. # 2 楼答案

    在我看来,最好的方法就是按照Yoni的建议进行重构。除了更改方法的签名(可能因为它是在接口中定义的而不可能),您的原始方法可以调用另一个方法,您可以传递要使用的PrintStream

    public void withdraw(double amt) {
        performWithdraw(amt, System.out);
    }
    
    void performWithdraw(double amt, PrintStream errorStream) {
        double bal = getBalance();
        if(bal >= amt) {
            super.setBalance(bal - amt);
            if(bal < minBalance) {
                super.setBalance(bal - amt - maintFee);
            }   
        } else {
            errorStream.println("Error: Not enough funds for withdraw");
        }       
    }
    

    您的测试类(位于同一个包中,并且therfor能够访问performWithdraw)如下所示:

    @Test
    void testInvalidWithdraw() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos, true, "utf8");
        Savings s = new Savings(500.00, 30.00, "111", "Andrew Green", 400.00);
        s.performWithdraw(600.00, ps);
        assertEquals(400d, s.getBalance());
        assertEquals("check error message", "Error: Not enough funds for withdraw", baos.toString("utf8"));
    }
    

    顺便说一句:您应该测试余额是否保持不变(在我的示例中,我添加了一个相应的assertEquals),并且您还应该检查边缘情况,即检查您在提取400.01时是否收到错误消息。还应检查边缘案例是否收取维护费用

    BTW2:使用double表示货币金额是一件坏事[TM]。学习JUnit没关系,但对于真正的应用程序[TM],你应该使用BigDecimal