2010-04-02 27 views
17

Tôi có một đoạn mã đọc dữ liệu từ một tệp. Tôi muốn lực lượng IOException trong mã này cho mục đích thử nghiệm (Tôi muốn kiểm tra xem mã ném một ngoại lệ tùy chỉnh chính xác trong trường hợp này).Buộc IOException trong khi đọc tệp

Có cách nào để tạo tệp được bảo vệ không đọc, chẳng hạn? Có thể giao dịch với một số kiểm tra bảo mật có thể giúp bạn?

Xin lưu ý rằng việc chuyển tên của một tệp không tồn tại không thể giúp, vì FileNotFoundException có một mệnh đề bắt riêng biệt.

Dưới đây là đoạn mã cho sự hiểu biết tốt hơn về câu hỏi:

BufferedReader reader = null; 
    try { 

     reader = new BufferedReader(new FileReader(csvFile)); 

     String rawLine; 
     while ((rawLine = reader.readLine()) != null) { 
      // some work is done here 
     } 

    } catch (FileNotFoundException e) { 
     throw new SomeCustomException(); 
    } catch (IOException e) { 
     throw new SomeCustomException(); 
    } finally { 
     // close the input stream 
     if (reader != null) { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       // ignore 
      } 
     } 
    } 
+0

Bạn có thể thử đọc một tập tin mà bạn không được phép để đọc. Trên Linux '/ proc/kcore' là một cược tốt, giống như'/etc/shadow'. –

+1

không phải là câu trả lời, mà là một quan sát. Bạn nên bọc IOException với ngoại lệ tùy chỉnh của bạn để giữ nguyên dấu vết ngăn xếp đầy đủ. tức là 'ném SomeCusomException mới (e) ' –

Trả lời

-1

Bạn luôn có thể ném của riêng IOException:

throw new IOException("Test IOException"); 
+0

Tôi đã thêm mã cho câu hỏi ban đầu. Có vẻ như bạn không hiểu nó. – DixonD

0

Bạn có thể làm ngoại lệ này tăng cho một tập tin đó là quá lớn.

2

Bạn có thể thử tạo tệp dưới dạng siêu người dùng và sau đó đọc tệp đó làm người dùng chuẩn. Có vấn đề về quyền ở đó. Hoặc chỉ cần chmod điều giả sử bạn đang trên Linux. Bạn cũng có thể thử đặt nó vào một thư mục ẩn/được bảo vệ.

+0

Bạn có thể cung cấp một ví dụ sẽ hoạt động trên bất kỳ hệ điều hành đích nào không? – DixonD

+3

Vì các hệ điều hành khác nhau khá nhiều về mặt những gì họ làm với hệ thống tệp và quản lý người dùng của họ, điều đó thật khó khăn. Bạn có thể thử sử dụng đối tượng java File và gọi setReadable/setWritable trên đó - xem http://java.sun.com/javase/6/docs/api/java/io/File.html#setReadable%28boolean%29 –

+1

Đáng kinh ngạc câu trả lời thông minh. Nó thậm chí còn đa nền tảng. Nó không yêu cầu một khuôn khổ mocking bên thứ 3. Nên là câu trả lời được chấp nhận nếu bạn hỏi tôi. – jontejj

4

Nếu bạn có thể cấu trúc lại mã một chút để chấp nhận một Reader, chứ không phải tên tệp, bạn có thể sử dụng mocks. Với EasyMock bạn có thể tạo một Trình đọc giả, và đặt nó để ném IOException khi gọi bất kỳ phương thức nào bạn muốn. Sau đó, bạn chỉ cần vượt qua nó để phương pháp này để được kiểm tra, và xem những gì sẽ xảy ra :-)

void readFile(Reader reader) throws SomeCustomException { 
    try { 
     String rawLine; 
     while ((rawLine = reader.readLine()) != null) { 
      // some work is done here 
     } 

    } catch (FileNotFoundException e) { 
     throw new SomeCustomException(); 
    } catch (IOException e) { 
     throw new SomeCustomException(); 
    } finally { 
     // close the input stream 
     if (reader != null) { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       // ignore 
      } 
     } 
    } 
} 

thì mã kiểm tra:

mockReader = createMock(Reader.class); 
expect(mockReader.readLine()).andThrow(
     new IOException("Something terrible happened")); 
replay(mockReader); 

objectToTest.readFile(reader); 
+0

Thật đáng tiếc là tôi không thể thay đổi mã được thử nghiệm – DixonD

+1

@DixonD: nếu bạn không thể thay đổi mã và nó không được thiết kế chính xác, thì bạn không thể kiểm tra đơn vị đó. Điều tốt nhất bạn có thể hy vọng là làm một số thử nghiệm tích hợp. –

1

Bạn có thể sử dụng một thư viện Mock như Mockito hoặc Easymock (+classpath) tạo đối tượng tệp Mock (các lib mới hơn có các phần mở rộng của trình nạp lớp cho phép bạn giả lập các lớp cụ thể như File), hoặc có thể hợp tác với một cái gì đó như PowerMock (see blog) và có một mô hình được tạo cho cuộc gọi hàm tạo và ném ngoại lệ thích hợp khi được gọi.

+0

Không có cách nào để vượt qua giả lập trong mã – DixonD

+0

Đã chỉnh sửa câu trả lời để liên kết đến bài viết blog về cách sử dụng PowerMock cho loại thử nghiệm này (thúc đẩy thao tác ClassLoader) – jayshao

7

Tuyên bố từ chối trách nhiệm: Tôi chưa thử nghiệm tính năng này trên nền tảng không phải Windows, vì vậy nó có thể có các kết quả khác nhau trên nền tảng có đặc điểm khóa tệp khác nhau.

Nếu bạn khóa các tập tin trước đó, bạn có thể kích hoạt một IOException khi một cái gì đó cố gắng để đọc từ nó:

java.io.IOException: The process cannot access the file because another process has locked a portion of the file 

này hoạt động ngay cả khi bạn đang ở trong cùng một sợi.

Dưới đây là một số mẫu mã:

final RandomAccessFile raFile = new RandomAccessFile(csvFile, "rw"); 
raFile.getChannel().lock(); 
+2

Không hoạt động cho tôi - sử dụng Ubuntu .. nhưng ý tưởng là tốt đẹp :) –

+0

hoạt động trên cửa sổ – panny

1

Bạn có thể buộc một ngoại lệ bằng cách gọi phương thức đóng trên BufferedReader của bạn:

reader = new BufferedReader(new FileReader(csvFile)); 

    // invoke the Close() method. 
    reader.Close(); 

    String rawLine; 
    while ((rawLine = reader.readLine()) != null) { 
     // some work is done here 
    } 

Tôi hy vọng rằng sẽ giúp.

0

Tôi khuyên bạn không nên sử dụng FileNotFoundException. Nếu bạn muốn ném một ngoại lệ cụ thể cho tệp không tồn tại, tôi sẽ kiểm tra csvFile.exists().

Ví dụ: bạn có thể tạo csvFile một thư mục. Tôi đã thử nghiệm mã của bạn và nó ném:

File file = new File("actually_a_directory.csv"); file.mkdir(); yourCode(file); // throws FileNotFoundException: "actually_a_directory.csv (Access is denied)"

Theo tôi, một tập tin thực sự trở thành một thư mục là không giống như FileNotFound, nhưng nó đóng vai trò như nhau trong java.

0

Xác định trong thử nghiệm của bạn một FileInputStream quá tải mà ném một ngoại lệ

FileInputStream s; 
try { 
    s = new FileInputStream(fileName) { 

      @Override 
      public int read() throws IOException { 
       throw new IOException("Expected as a test"); 
      } 
     }; 
} catch (FileNotFoundException e) { 
    throw new RuntimeException(e.getMessage(), e); 
} 
Các vấn đề liên quan