2013-06-13 36 views
9

Tôi thấy rất nhiều câu hỏi về cách làm cho Intellij vi phạm các ngoại lệ. Tôi đang cố gắng làm điều gì đó khác: Tôi muốn ném một ngoại lệ tại một điểm dừng để tôi có thể thấy điều gì sẽ xảy ra nếu một ngoại lệ xảy ra ở mã đó.Trong Intellij, làm thế nào tôi có thể ném một ngoại lệ tại một điểm ngắt?

Tôi đã tìm ra cách để ép buộc điều này. Ví dụ: nếu tôi có một biến được gọi là willBeUsed, tôi có thể nhấn điểm ngắt và thêm một chiếc đồng hồ có ghi willBeUsed = null. Điều này sẽ kích hoạt NullPointerException cuối cùng là.

Nhưng tôi đang ở trong một tình huống mà tôi muốn ném một số IOException để xem điều gì xảy ra. Không có cách nào để lừa mã của tôi để làm điều đó. Khi tôi thêm một chiếc đồng hồ có ghi số throw new IOException() nó cho tôi một lỗi nói rằng, "mã thông báo không mong muốn".

Là một công việc xung quanh, tôi có thể sửa đổi mã để ném ngoại lệ và triển khai lại. Nhưng tôi tự hỏi nếu có một cách để làm điều này trong trình gỡ rối mà không sửa đổi mã nguồn.

+3

Nó không chắc rằng có một cách để làm những gì bạn đang yêu cầu. Tôi sẽ đề nghị xem xét một thiết kế khác dễ dàng tạo điều kiện cho loại thử nghiệm này - ví dụ [tiêm phụ thuộc] (http://en.wikipedia.org/wiki/Dependency_injection). –

+1

@RobI tiêm phụ thuộc là tốt. Tôi không thấy nó giúp tôi như thế nào. Bạn có thể xây dựng? –

+0

Ý tưởng ngắn: tạo một giao diện để thực hiện những gì bạn đang làm trong khối mã đôi khi làm tăng ngoại lệ (giả sử 'IODoer' với phương thức' do() '). Việc thực thi thực sự của bạn là trong một lớp cụ thể 'IODoerImpl', với tất cả mã thực, nhưng bạn có một lớp' TestIODoer' cụ thể khác, điều này làm tăng một ngoại lệ mỗi khi bạn gọi phương thức 'do()' hoặc mọi thời gian khác, hoặc bất cứ khi nào ... Thông thường chương trình của bạn sử dụng việc triển khai thực sự, nhưng trong quá trình thử nghiệm, bạn có thể tiêm lớp thử nghiệm này thay thế. –

Trả lời

6

Làm thế nào về việc đặt báo cáo kết quả throw trong một khối if, và chỉ thay đổi điều kiện, ví dụ .:

boolean shouldThrowException = false; 
// .... 
if (shouldThrowException) //place breakpoint here 
{ 
    throw new IOException(); 
} 

Khi bạn nhấn breakpoint, thay đổi giá trị của shouldThrowException là true.

+0

Tôi khá nhiều đã cho điều này như là một workaround trong câu hỏi của tôi. Nhưng nếu đó là cách duy nhất, tôi đoán đó là cách duy nhất. –

+0

Tôi xin lỗi, tôi phải bỏ lỡ nó trong câu hỏi của bạn, xin lỗi vì không quá hữu ích .. – MByD

1

Tôi không thể xem cách thực hiện việc này. Tôi đã thử hai cách tiếp cận (có lẽ ý tưởng của tôi sẽ dẫn đến một số ý tưởng khác

1) Tôi đã cố gắng sử dụng biểu thức "nhật ký được đánh giá" của trình gỡ rối "throw new IOException() nhưng tất cả những gì tôi nhận được là một thông báo rằng IDEA không thể đánh giá biểu thức .

2) Tôi cũng đã cố gắng đặt điểm ngắt và khi nó dừng, tôi mở hộp thoại "đánh giá biểu thức" để ném ngoại lệ mới nhưng không hoạt động.

Tôi không nghĩ trình gỡ lỗi có thể ném ngoại lệ. @ Binyamin của giải pháp sẽ làm việc nhưng bạn đã đề cập rằng trong câu hỏi của bạn. Tôi chỉ có thể thêm IDEA vào IDEA có thể bỏ chọn hộp kiểm "tạm ngừng" và nhập shouldThrowException = true vào hộp "biểu thức đã đánh giá nhật ký". Điều này sẽ làm cho trình gỡ lỗi chỉ thay đổi giá trị (và ghi nhật ký) nhưng không dừng lại, điều này thật tuyệt vời trong mã có nhiều luồng đồng thời.

1

Tôi không biết nếu bạn đã thử điều này nhưng bạn có lẽ có thể tạo một phương pháp tĩnh chỉ ném IOException và sau đó gọi phương thức đó bằng cách phát hành Evaluate Expression.

Simple mã ví dụ:

package com.stackoverflow; 

import java.io.IOException; 

public class Main { 
    public static void main(String[] args) { 

     doStuff(); 
    } 

    private static void throwException() throws IOException { 
     throw new IOException(); 
    } 

    private static void doStuff() { 
     System.out.println("doStuff"); 
    } 
} 

Đặt một breakpoint trên System.out.println dòng:

enter image description here

Mang lên Evaluate Expression... cửa sổ và gọi throwException phương pháp (đánh giá) và sau đó bạn sẽ lấy dấu vết ngăn xếp từ bên trong doStuff:

enter image description here

Tất nhiên ngoại lệ sẽ ở trong throwException nhưng bạn cũng thấy toàn bộ ngăn xếp cuộc gọi.

+0

Đúng, điều đó có hiệu quả. Nhưng tôi vẫn phải triển khai lại. Nhưng, những gì sẽ được gọn gàng là để đặt này trong một thư viện và sau đó tôi có thể gọi nó bất cứ khi nào tôi cần trên bất kỳ dự án. Bằng cách này, tôi sẽ không cần sửa đổi bất kỳ tệp nguồn nào trong dự án chính hoặc triển khai lại. Tôi có thể sử dụng một phạm vi maven để nó không được triển khai khi tôi gói. –

+0

@tieTYT Đúng đó là suy nghĩ của tôi. – maba

+0

Tôi đã thử điều này và đầu ra của bảng điều khiển không hiển thị ngoại lệ trong đó. Tôi nghĩ rằng nó đánh giá ngoại lệ trong trường hợp riêng của nó để nó không ảnh hưởng đến chủ đề chính. –

1

Có một cách khác để bạn tận dụng lợi thế của JVM HotSwapping.

Giả sử bạn đang triển khai mã cho một số máy chủ. Sau đó, khi bạn khởi động ứng dụng, hãy chắc chắn rằng bạn bật gỡ lỗi từ xa (mà tôi nghĩ rằng bạn có kể từ khi bạn đang gỡ lỗi và đang nói về triển khai). Nếu không thì nó sẽ làm việc đồng đều tốt trong trình gỡ lỗi cục bộ.

Bây giờ tôi có hai lớp, Chính và Khác.

package com.stackoverflow; 

import java.io.IOException; 

public class Main { 
    public static void main(String[] args) throws IOException { 
     doStuff(); 
    } 

    private static void doStuff() throws IOException { 
     System.out.println("doStuff"); 
     Other.otherStuff(); 
    } 

    public static void throwException() throws IOException { 
     throw new IOException(); 
    } 
} 


package com.stackoverflow; 

import java.io.File; 
import java.io.IOException; 

public class Other { 
    public static void otherStuff() throws IOException { 
     File file = new File("Some_File.txt"); 
     file.createNewFile(); 
    } 
} 

Các throwException() có thể được đặt ở bất cứ đâu miễn là nó là "toàn cầu" có sẵn trong một số lớp util ví dụ. Bây giờ nó chỉ được đặt trong lớp chính của tôi cho thuận tiện.

Bây giờ chúng ta có thể có một breakpoint đặt trong phương pháp doStuff() của chúng tôi và trong khi bị giam giữ ở đó chúng ta có thể thay đổi mã trong phương pháp otherStuff() để nó gọi throwException() phương pháp tĩnh của chúng tôi.

public static void otherStuff() throws IOException { 
    Main.throwException(); 
    File file = new File("Some_File.txt"); 
    file.createNewFile(); 
} 

Chúng ta phải gọi một số phương pháp thay vì cách gọi throw new IOException() bởi vì nếu không chúng ta sẽ có lỗi với Unreachable statement.

Sau đó chúng ta có thể nhấn tổ hợp phím Ctrl + phím Shift +F9 phải biên dịch lại lớp khác. Nó sẽ được HotSwapped (một hộp thoại sẽ hỏi nếu bạn thực sự muốn làm điều này).

Sau đó nhấn tiếp tục và ngoại lệ sẽ được ném.

Mã này sau đó có thể được hoàn nguyên về trạng thái bình thường.

Điều tốt về điều này là lớp được biên dịch lại thậm chí sẽ được trao đổi nóng "qua dây" với máy từ xa.

Điều quan trọng là mã mà bạn biên dịch lại phải nằm trong một lớp khác. Cùng một lớp mà bạn có điểm dừng của bạn sẽ không được tải lại chính xác.

Là một công việc xung quanh, tôi có thể sửa đổi mã để ném ngoại lệ và triển khai lại. Nhưng tôi tự hỏi nếu có một cách để làm điều này trong trình gỡ rối mà không sửa đổi mã nguồn.

Bạn sẽ sửa đổi mã nhưng chỉ vào thời điểm bạn muốn, trong trình gỡ lỗi. Sau đó bạn có thể quay trở lại thay đổi nhỏ và biên dịch lại để trao đổi nóng lại mã cũ.

Tôi hy vọng bạn có ý tưởng (không có ý định chơi chữ).

Tôi có thể thêm ảnh chụp màn hình nếu bạn muốn.

+1

OK có thể hoạt động. Theo kinh nghiệm của tôi, HotSwapping hoạt động như 30% thời gian, nhưng điều này có thể ổn. Cảm ơn –

+1

@tieTYT Hy vọng nó hoạt động cho bạn hơn 30% thời gian. Tôi ra khỏi ý tưởng bây giờ, đây là tốt nhất tôi có thể đến với :-) – maba

1

Tôi nghĩ rằng nó không khả dụng (cho đến 2018.1) để thực hiện mà không có bất kỳ thay đổi nào về mã.

Bạn có thể thấy sự cố JetBrains: IDEA-148408. Có yêu cầu thêm tính năng này vào IntelliJ IDEA.

CẬP NHẬT: Kể từ phiên bản 2018,1 nó có sẵn

Các vấn đề liên quan