【问题标题】:Junit test fails when I use try and catch block. Why?当我使用 try 和 catch 块时,Junit 测试失败。为什么?
【发布时间】:2021-02-16 14:58:53
【问题描述】:

我想使用 Junit 测试框架测试我的 java 代码。在我的源代码中,我使用 try 和 catch 块来处理异常。在我的测试方法中,我想测试这种方法。如果我的源代码返回一些异常并且它在我的测试方法中匹配,我的测试将通过,否则失败。但是我的代码没有通过这个测试。

我找到了解决方法,但我想使用 try 和 catch 块。我也来分享一下。

不工作 我的源代码(我想测试这个方法)

    public boolean isCreateAccount(String amount) {
    
    try { 
        
        Double balance = Double.parseDouble(amount);
        
        if(balance < 0)
             throw new Exception();

    
    } catch (Exception e) { 
        System.out.println("WARNING: Invalid amount!");
    } 
    
         return false;
    
    }

这是我在 JUnit 中的测试方法

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void testCreateAccountInvalidAmount() {

    expectedException.expect(Exception.class);
    accountServices.isCreateAccount("-100");    
    
}

工作中 这种方式可行,但我想使用 try 和 catch 块 我的源代码(我想测试这个方法)

    public void isCreateCheckingAccount(String amount) {
            
        Double balance = Double.parseDouble(amount); 

        if(balance < 0)
             throw new Exception();

    
     }

这是我在 JUnit 中的测试方法

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void testCreateAccountInvalidAmount() {

    expectedException.expect(Exception.class);
    accountServices.isCreateAccount("-100");    
    
}

【问题讨论】:

  • 你是说期望测试抛出异常。你的测试方法会抛出异常吗?
  • 看起来周围的 try catch 块正在捕获异常,阻止抛出任何异常
  • @macedonboy - 我完全同意你的看法。我对 Junit 没有足够的经验。在我的 isCreateAccount 方法中,我创建异常并捕获它,因为我的测试方法没有得到它。我不确定如何使用 try and catch 来解决这个问题。也许没有解决办法。
  • 如果您坚持这样做,您总是可以重新抛出异常,但您也可以更改 if 语句以打印消息,然后抛出异常
  • @Savior - 不,假设您在 mainDriver 中创建了一个方法。此方法引发异常。我想在我的测试方法中使用 Junit 测试这个期望。

标签: java junit try-catch throw


【解决方案1】:

我想通了这个问题。谢谢你们的帮助。我在这里分享我的解决方案。如果您遇到此类问题,希望对您有所帮助。

//这个代码在我的服务层...

@Override
public boolean isCreateAccount(String amount) {
    
    try { 
            
        isValidAmount(amount);
        double balance = Double.parseDouble(amount);    
        createAccount(balance);
        return true;
        
    } catch(NullPointerException e) {
        log.warn("WARNING: Empty Amount!");
        System.out.println("\nWARNING: Empty Amount!");
        
    } catch (NumberFormatException e) { 
        log.warn("WARNING: Invalid amount!");
        System.out.println("\nWARNING: Invalid amount!");
        
    } catch (NegativeAmountException e) {
        log.warn("WARNING: Amount must have a positive number!");       
        System.out.println("\nWARNING: Amount must have a positive number!");
        
    } catch (InsufficientAmountException e) {
        log.warn("WARNING: Not enough money to open a checking account!");
        System.out.println("\nWARNING: Not enough money to open a checking 
    account!");
    }
    
    return false;
}

//这个代码在我的服务层...

@Override
public void isValidAmount(String money) {
    
    if(money == null || money.length() == 0) {
        throw new NullPointerException("Empty Amount");
    }
    
    double amount = 0.0D;
    
    try {
        amount = Double.parseDouble(money);         
    } catch (NumberFormatException e) {
        throw new NumberFormatException("Invalid Amount");
    } 
        
    if(amount < 0.0D) {
        throw new NegativeAmountException("Negative Amount");
    }       
    
    if(amount < 25.0D) {
        throw new InsufficientAmountException("Insufficient Amount");
    }

}

//这个代码在我的Junit测试类中

@Test
public void testCreateCheckingAccountNullAmount() {
    expectedException.expect(NullPointerException.class);
    expectedException.expectMessage("Empty Amount");
    accountServices.isValidAmount("");              
}

@Test
public void testCreateCheckingAccountInvalidAmount() {
    
    expectedException.expect(NumberFormatException.class);
    expectedException.expectMessage("Invalid Amount");
    accountServices.isValidAmount("a100");          
}

@Test
public void testCreateCheckingAccountNegativeAmount() {
    expectedException.expect(NegativeAmountException.class);
    expectedException.expectMessage("Negative Amount");
    accountServices.isValidAmount("-10");
}

@Test
public void testCreateCheckingAccountInsufficientAmount() {
    expectedException.expect(InsufficientAmountException.class);
    expectedException.expectMessage("Insufficient Amount");
    accountServices.isValidAmount("10");
}

【讨论】:

  • 我担心这不是代码审查论坛,但我很高兴您找到了适合您的解决方案 :-) 祝您的应用程序好运。顺便说一句,如果我的解决方案有帮助,请接受。
【解决方案2】:

这会做你想做的事:

public boolean isCreateAccount(String amount) throws Exception {

    Double balance = Double.parseDouble(amount);

    if (balance < 0) {
        System.out.println("WARNING: Invalid amount!");
        throw new Exception();
    }

    return false;
}

虽然返回 false 没有多大意义。

如果你真的想要那个 try catch 块:

public boolean isCreateAccount(String amount) throws Exception {

    try {
        Double balance = Double.parseDouble(amount);
        if (balance < 0) {
            System.out.println("WARNING: Invalid amount!");
            throw new Exception();
        }
    } catch (Exception e) {
        throw e;
    }

    return false;
}

这些基本测试适用于两个版本:

public class AccountTest {

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Test
    public void testCreateAccountInvalidAmount() throws Exception {
        Account accountServices = new Account();
        expectedException.expect(Exception.class);
        accountServices.isCreateAccount("-100");
    }

    @Test
    public void testCreateAccountZeroAmount() throws Exception {
        Account accountServices = new Account();
        assertFalse(accountServices.isCreateAccount("0"));
    }

    @Test
    public void testCreateAccountValidAmount() throws Exception {
        Account accountServices = new Account();
        assertFalse(accountServices.isCreateAccount("1"));
    }
}

【讨论】:

  • 对于这部分,是的,您可以使用 throws,但我需要在我的服务层中尝试和捕获块。谢谢。
  • 扔e;它不起作用。我有另一个问题。我的代码将返回布尔值,也可能引发异常。当我根据返回类型(布尔值)测试我的代码以检查 iscreateaccount 时,它可以工作。也许 Junit 只等待一种返回类型。异常或布尔值??也许我需要为此 isCreateAccount 编写测试方法??
  • 您不能同时拥有异常和布尔值。它是一个或另一个,isCreateAccount 返回的唯一布尔值是 false。
  • 我认为主要问题是catch,因为在我抛出异常后,我会在我的方法中捕获它并处理它。我将在我的测试类中编写测试方法,我会在那里抛出异常,然后我会将它与我的预期期望变量进行比较。如果有人找到不同的方法,我会尝试。谢谢@macedonboy
  • @Isa,什么不起作用?,我已经包含了一个版本的 isCreateAccount,它可以按预期工作
【解决方案3】:

看看你的方法。它具有以下行为:

  • 如果金额为负数或不是数字,它会向 sysout 打印一些内容(这很糟糕;您不应该像这样混合职责;您的帐户工具肯定不是您的 UI 层,但这是次要问题)。否则它什么也不打印。

  • 然后,不管你传入什么,它都会打印 false。

所以,这个方法的可观察行为是它返回 false,并且它打印一些东西到 sysout。

测试它是否返回 false 是微不足道的; assertFalse(services.isCreateAccount("100") 会做到这一点(不过,大概您的方法总是返回 false 的事实实际上是一个错误)。

测试它是否打印到 sysout 是很复杂的。这是因为你不应该在那里打印任何东西的根本问题。如果输出是要点的一部分,那么不要打印到System.out,而是将一些输出抽象(可能是java.io.PrintWriter)传递给AccountServices,这样您就可以传递一些变体作为测试的一部分;可以配置为检查是否在此处显示某些预期输出的变体。

您似乎认为这个方法会抛出一些东西。它没有 - 它捕捉一些东西。在junit中,说:“我期望这个异常”意味着您期望它从方法中消失,即相反:该方法没有捕获该异常,甚至该方法显式抛出该异常。

【讨论】:

  • 谢谢。在我的测试用例中,输入是“100”。我不测试“aaa100”,但我理解你的方法。我想在服务层测试我的代码,我需要 try and catch 块。我想我在我的测试类中编写了一个测试方法并使用“throw new Exception()”你怎么看?
猜你喜欢
  • 2010-10-16
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
  • 2022-11-10
  • 2011-09-29
  • 2012-10-08
  • 1970-01-01
相关资源
最近更新 更多