当else语句将错误消息输出为String时,JUnit测试方法



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

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测试。我只需要在testRetrowThree((上得到帮助。非常感谢。

@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"
}

在我看来,最好的方法是按照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");
}       
}

您的测试类(位于同一个包中,以便能够访问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"));
}

BTW:你应该测试余额是否保持不变(我在我的例子中添加了一个相应的assertEquals(,你也应该检查边缘情况,即检查你在提取400.01时是否收到错误消息。边缘案例还应检查是否收取维护费。

BTW2:使用double计算货币金额是件坏事[TM]。对于学习JUnit,这是可以的,但对于Real Applications[TM],您应该例如使用BigDecimal

有几种方法可以实现这一点:

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

此外,还有一点需要注意:用有意义的名称来命名测试方法会有很大帮助,例如testWithdrawWithoutFunds,而不是通用名称testOnetestTwo等。

最新更新