2014-07-09 43 views
0

我正在瀏覽stackoverflow以找出有關使用jUnit進行測試的常見建議,但仍有幾個問題。我明白,如果它是複雜的方法進行測試,最好的辦法是將其拆分成小的獨立部分並測試每個部分。但問題是 - 爲什麼我應該這樣做,如果所有這些小部件都容易理解,並且我可以「視覺化」測試它。我還沒有經歷過開發複雜的應用程序,這涉及到許多方法,這些方法必須被測試覆蓋,但我無法想象爲什麼測試提供明顯結果的大方法的部分是有用的。 下一個問題是關於DAO方法測試。坦率地說,我也不明白如何測試它們。你可以看看下面的片段,給我一個想法,測試下列方法的方法是什麼?先謝謝你。jUnit - 意見

1.什麼可以用這種方法測試?

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; 
    } 
+1

你的問題是合理的,但我建議在每個堆棧溢出問題中提出一個問題,這樣每個問題都可以有一個特定的標題和答案。你可以編輯這個只包括你的第一個問題。 –

回答

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,並返回選定數據的列表。 當你編寫單元測試時,要確保你的代碼是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,你會發現如果有SQLException它將返回null。您認爲列表中的內容實際上是null,因爲您無法連接到數據庫,這意味着您必須檢查該內容。

TL; DR

測試您的方法做了什麼,它做了什麼correctly

1

沒有明確的「對」與「錯」的編寫測試的時候,雖然你會發現噸的書籍和文章,但這裏是一些(個人)的建議來指導你,特別是關於使用JUnit:

  • 單元測試測試您的代碼的一個單元。根據您的代碼,這不一定是一個類,但它是一個邏輯代碼片段,通常組合在一個類中。因此,在測試時,您必須能夠提供在測試代碼中使用的所有外部引用,或者將它們模擬出來(例如,通過使用框架,如Mockito)。
  • 這是一個很好的做法,一起實現代碼和測試代碼。我個人不喜歡「先測試」的想法,因爲這在許多情況下並不實用(我喜歡「測試優先對Fibonacci很好」的說法)。但是,在與代碼大致同時編寫測試時,它可以幫助您設計代碼,以便更好地進行測試。
  • 不要測試所有東西(例如getters,setters),測試是否合理。一個常見的建議是測試所有的東西,其中cyclomatic complexity高於2.這意味着,如果你有一段代碼,包含ifs或循環,每條可能的路徑都會使它更復雜,你的測試必須隨着它的範圍而去(理想情況下)路徑。通常這是不實際的,迫使你選擇合理的(並記錄原因)。
  • 如果你有一個測試需要幾個組件,那麼它不僅僅是一個單元測試。但往往這條線很難畫。例如,如果您需要數據庫連接,那麼它肯定不僅僅是單元測試 - 如果測試實體,您仍然可以爲其編寫JUnit測試。如果你需要一個組件容器(例如應用服務器),那麼像Arquillian這樣的框架可以幫助你。