jUnit - 建议

时间:2014-07-09 13:47:46

标签: java unit-testing junit

我正在浏览stackoverflow以找出有关使用jUnit进行测试的常见建议,但仍有几个问题。我明白,如果它是一个复杂的测试方法,最好的方法就是将它分成一个小的独立部分并测试每个部分。但问题是 - 如果所有那些小部件都易于理解,我为什么要这样做呢?我可以直观地测试它#34;我还没有开发复杂应用程序的经验,这些应用程序涉及许多必须由测试覆盖的方法,但我无法想象为什么测试提供明显结果的大方法的部分是有用的。 下一个问题是关于DAO方法测试。坦率地说,我也不了解如何测试它们。你能看看下面的片段,并告诉我哪些方法可以测试以下方法?提前谢谢。

1.用这种方法可以测试什么?

public List<InvoicesBean> setPaymentStateInBean(List invoicesData, float sumBalance) {
    float dueState;
    float currentInvoiceAmount;
    float sumBalanceAfterIteration = sumBalance;
    String paymentState;

    Collections.sort(invoicesData, new BeanSortByDate());

    Iterator iterator = invoicesData.iterator();
    while (iterator.hasNext()) {
        InvoicesBean invoicesBean = (InvoicesBean) iterator.next();
        dueState = getDueState(invoicesBean.getDueDate());
        currentInvoiceAmount = invoicesBean.getAmount();
        sumBalanceAfterIteration = sumBalanceAfterIteration - currentInvoiceAmount;
        paymentState = getPaymentState(dueState, sumBalanceAfterIteration);
        invoicesBean.setPaymentState(paymentState);
    }
    return invoicesData;
}

2.向DB发出请求并返回所选数据列表的方法:

public List<InvoicesBean> getInvoicesData(String selectedContractor){
        float sumBalance = getPaymentTotalAmount(selectedContractor);
        List<InvoicesBean> invoicesDataWithPaymentsState;
        PaymentStateOperations paymentStateOperations = new PaymentStateOperations();

        try {
            preparedStatement = connection.prepareStatement("SELECT invoice_num, date, due_date, amount FROM invoices WHERE contractor_id IN" +
                    "(SELECT contractor_id FROM contractors WHERE contractor_name=?)");
            preparedStatement.setString(1, selectedContractor);
            resultSet = preparedStatement.executeQuery();
            invoicesData = new ArrayList<InvoicesBean>();
            while (resultSet.next()) {
                InvoicesBean invoicesBean = new InvoicesBean();
                invoicesBean.setNumber(resultSet.getString(1));
                invoicesBean.setDate(resultSet.getString(2));
                invoicesBean.setDueDate(resultSet.getString(3));
                invoicesBean.setAmount(resultSet.getFloat(4));
                invoicesData.add(invoicesBean);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        invoicesDataWithPaymentsState = paymentStateOperations.setPaymentStateInBean(invoicesData, sumBalance);
        return invoicesDataWithPaymentsState;
    }

2 个答案:

答案 0 :(得分:1)

您希望测试时知道在开发过程中您没有破坏任何东西。 当您编写单元测试时,要确保您的代码为robust,这意味着它会正常失败或以正确的方式处理错误的输入。

可能不需要总是测试琐碎的函数,但是在非平凡和平凡的方法之间划线?对于每个开发人员来说都是不同的,你应该注意的是not to test语言本身,我会说这类似于(例子是愚蠢的,但只是为了证明一点):

public String areBothTrue(bool a, bool b) {
    return a && b;
}

但是假设你有一个非常简单的方法只增加两个整数,那值得测试的是什么?

public int sum(int a, int b) {
   return a+b;
}

这种方法总是会产生可预测的结果,但是input呢?假设输入为Integer.MAX_NUM5,结果是什么(提示它不是两个值的总和)? 在这种情况下,重要的是这个方法的context是什么,如果它的目的只是以Java的方式对两个整数求和那么它就完全没问题了,但是如果它应该添加一个值,那么让在我的银行账户里说,如果我非常富有,我很快就会成为一个非常贫穷的人。 :(

我想说的是,你不应该把单元测试看作是测试你的功能是做它的功能,你应该测试的是它做什么,做什么correctly即使是输入很糟糕。

我不会过多地浏览你的片段,因为我不知道他们需要什么,但如果你看getInvoicesData你可以看到它会返回null如果有的话一个SQLException。这意味着您认为列表的内容实际上是空的,因为您无法连接到数据库,这意味着您必须检查它。

TL; DR

测试您的方法是做什么的,它做什么correctly

答案 1 :(得分:1)

没有明确的&#34;权利&#34;并且&#34;错误&#34;在编写测试时,虽然你会发现大量的书籍和文章,但这里有一些(个人)建议来指导你,特别是关于使用JUnit:

  • 单元测试测试代码的一个单元。根据您的代码,这不一定是单个类,但它是一段逻辑代码,通常组合在一个类中。因此,在测试时,您必须能够提供测试代码中使用的所有外部引用或将其模拟出来(例如,通过使用Mockito等框架)。
  • 将代码和测试代码一起实现是一种很好的做法。我个人不喜欢测试优先的想法,因为这对许多情况都不实用(我喜欢引用&#34;测试优先适用于Fibonacci&#34;)。但是,在与代码大致相同的时间编写测试时,它可以帮助您设计代码,使其更易于测试。
  • 不要测试所有东西(例如吸气剂,孵化器),测试合理。一个常见的建议是测试cyclomatic complexity高于2的所有内容。这意味着,如果你有一段带有ifs或循环的代码,每个可能的路径都会使它变得更复杂,你的测试必须适应它并且去(理想情况下)通过所有路径。这通常是不实际的,迫使你选择合理的(并记录原因)。
  • 如果您的测试需要多个组件,那么它不仅仅是一个单元测试。但通常这条线很难画出来。例如,如果您需要数据库连接,那么它肯定不仅仅是一个单元测试 - 如果测试实体,您仍然可以为它编写JUnit测试。如果您需要组件的容器(例如应用服务器),那么像Arquillian这样的框架可以帮助您。