Có bất kỳ khung Hệ thống Tệp Giả mạo nào dành cho Java không? [đóng cửa]


83

Tôi đang giới thiệu các bài kiểm tra trong một dự án sử dụng nhiều hoạt động IO (hệ thống tệp, trong trường hợp này). Hệ thống liên tục mở / đóng tệp, kiểm tra xem tệp có tồn tại hay không, xóa chúng, v.v.

Rõ ràng là việc chế nhạo thường xuyên sẽ không có ích gì nhiều, vì điều đó sẽ khiến các bài kiểm tra của tôi khó thiết lập và suy luận. Mặt khác, có một hệ thống tệp giả mạo sẽ rất tuyệt vời và tôi nghĩ, khá dễ dàng để thiết lập.

Có vẻ như những người chơi ruby ​​đã làm điều đó một lần nữa, và có chính xác những gì tôi đang yêu cầu ở ruby: http://ozmm.org/posts/fakefs.html .

Có điều gì tương tự từ xa cho Java không?


1
Có vẻ như một cấp ứng dụng dễ thực hiện hơn trong các ngôn ngữ không có hệ thống kiểu tĩnh. Trong Java, một File / FileInputStream / FileOutputStream sẽ luôn tham chiếu đến hệ thống tệp của hệ thống cơ bản - nếu bạn không vá VM.
Paŭlo Ebermann

Có những giao diện như JavaFileManager hoặc FileSystemView mà bạn có thể triển khai, nhưng hầu hết các chương trình sẽ không sử dụng chúng.
Paŭlo Ebermann

@ Nhận xét thứ nhất: Tôi nhận thức rõ điều đó. Tôi hiện đã thay thế tất cả việc sử dụng Tệp thành Tên tệp của riêng tôi chỉ chứa tên tệp dưới dạng chuỗi. Tất cả logic IO được tập trung trên giao diện IFileSystem. Vấn đề tôi đang gặp phải là nó vẫn giống như cả ngày làm việc để triển khai hệ thống tệp giả mạo theo cách tôi cần (với hỗ trợ tệp + thư mục + tệp ẩn + đổi tên + chỉ lấy đường dẫn từ tên tệp + ...) và kiểm tra nó, để biết nó thực sự là đúng.
elysium nuốt chửng

1
Vì bạn đã đề cập đến Ruby trong OP, nên tôi chỉ muốn nói thêm ở đây rằng cũng có một thứ tương đương trong C #, System.IO.Abstraction mà tôi đã bắt đầu sử dụng gần đây và khá tốt.
julealgon

Câu trả lời:


52

Google có triển khai mã nguồn mở, trong bộ nhớ của FileSystemProvider của Java 7. Các dự án được gọi là jimfs .


Nếu bạn sử dụng Java 6 hoặc phiên bản cũ hơn, có một giải pháp thay thế: Tôi đã sử dụng Apache Commons VFS trước đây để đạt được thành công lớn. Nó có vẻ giống như FileSystemProvider tùy chỉnh mà một trình trả lời khác được đề cập là trong Java 7.

Nó được tải sẵn một số cài đặt hệ thống tệp: Tệp, RAM, S / FTP và Jar. Tôi cũng đã thấy một plugin cho S3 .


6
+1 tới jimfs, cho phép tôi kiểm tra mã của mình mà không có một thay đổi nào. (Tôi đã sử dụng Pathmột cách tình cờ)
user1071136

35

Trong Java 6 trở về trước, rất khó vì các lớp thích FileFileInputStreamkhông cung cấp cách nào để gửi đến các "hệ thống tệp ảo" khác nhau trong không gian Java.

Trong Java 7, có hỗ trợ cho các hệ thống tệp ảo; xem phần Phát triển nhà cung cấp hệ thống tệp tùy chỉnh . Tôi không biết liệu điều này có cho phép bạn làm những gì bạn muốn làm hay không, nhưng đó là một nơi tốt để bắt đầu tìm kiếm.


Meh. Thực tế là dường như không có bất kỳ hệ thống tệp giả mạo nào, tôi đoán tôi sẽ chỉ thực hiện một cách triển khai tối thiểu một mình. Tôi không giành được gì bằng cách sử dụng FileSystemProvider

Trên thực tế, bạn có thể giành chiến thắng bằng cách sử dụng FileSystemProvider:

  • Bạn triển khai thứ gì đó (nếu được phát hành theo giấy phép nguồn mở) có thể rất hữu ích cho những người khác ở vị trí của bạn và cho các mục đích khác.

  • Bạn sẽ dễ dàng hơn nếu quyết định chuyển sang FileSystemProvider mà người khác có thể đang làm việc ngay bây giờ.


Thú vị, nhưng vì nó dường như tôi vẫn sẽ phải thực hiện các hệ thống tập tin bằng bản thân mình, không phải là hữu ích ;-(
ngấu nghiến Elysium

6
Ít nhất nó cho phép bạn làm điều đó. Và như chính bạn đã nói - "nó sẽ dễ dàng thiết lập" .
Stephen C

Meh. Thực tế là dường như không có bất kỳ hệ thống tệp giả mạo nào, tôi đoán tôi sẽ chỉ thực hiện một triển khai tối thiểu một mình. Tôi không giành được gì bằng cách sử dụng FileSystemProvider.
elysium nuốt chửng vào

@devoured elysium - xem bản cập nhật của tôi.
Stephen C,

2
1 cho các đề xuất bằng văn bản và mã nguồn mở-ing một giải pháp
WickyNilliams

19

Bạn có thể sử dụng org.junit.rules.TemporaryFoldertừ gói JUnit :

Quy tắc TemporaryFolder cho phép tạo các tệp và thư mục được đảm bảo sẽ bị xóa khi phương pháp thử nghiệm kết thúc (cho dù phương pháp này đạt hay không thành công):

Thí dụ:

final TemporaryFolder testFolder = new TemporaryFolder();
testFolder.create();
final Path filePath = testFolder.newFile("input.txt").toPath();
final Path dirPath = testFolder.newFolder("subfolder").toPath();

Hoặc thoát khỏi .toPath()phần:

final File filePath = testFolder.newFile("input.txt");

TemporaryFolder không có trong bộ nhớ.
progonkpa

8

Bạn có thể tóm tắt việc sử dụng Filebằng cách sử dụng ý định "nơi nào đó để ghi dữ liệu" bằng cách thay đổi API của bạn thành sử dụng OutputStreamthay vì a File, sau đó chuyển API a FileOutputStreamtrong mã sản xuất của bạn, nhưng chuyển API a ByteArrayOutputStreamtừ các thử nghiệm của bạn. A ByteArrayOutputStreamlà một luồng trong bộ nhớ, vì vậy nó rất nhanh và bạn có thể chỉ cần kiểm tra nội dung của nó bằng cách sử dụng các phương pháp của nó - nó hoàn hảo để kiểm tra. Cũng có tương ứng ByteArrayInputStreamnếu bạn muốn đọc dữ liệu.

Hệ thống tệp nói chung khá nhanh - trừ khi bạn thực hiện rất nhiều I / O tệp trong các thử nghiệm của mình, tôi sẽ không bận tâm.

Lưu ý rằng việc tạo Fileđối tượng java không tạo tệp trên đĩa, tức là mã sau không gây ra bất kỳ thay đổi nào đối với đĩa:

File f = new File("somepath"); // doesn't create a file on disk

new File ("cái gì đó") sẽ không tạo một tệp trên đĩa nhưng nếu bạn cố gắng chạy hầu hết các phương pháp của nó, nó sẽ sử dụng hệ thống tệp. Hãy thử tập tin mới ( "xyz") getAbsolutePath () để xem những gì tôi có nghĩa là ...
Elysium nuốt

1
Tôi nghĩ mọi người đang cho rằng mối quan tâm chính của tôi là tốc độ. Không phải vậy.
devoured elysium

1
tôi thấy rằng việc trừu tượng hóa mọi tài nguyên như hệ thống tệp luôn luôn tốt (giống như cách bạn viết một lớp truy cập dữ liệu vào DB). điều này thường đạt được bằng cách viết một giao diện và một trình bao bọc mỏng xung quanh lớp cấp thấp nhất. nếu bạn sử dụng tính năng tiêm phụ thuộc ở cấp cao nhất của chương trình, bạn có thể rất dễ dàng truyền bá một hệ thống tệp giả (lưu ý rằng nó không nhất thiết phải sử dụng một khuôn khổ giả, chỉ cần một triển khai "giả" của giao diện) thông qua ứng dụng của bạn.
WickyNilliams

@devouredelysium new File("xyz").getAbsolutePath()hoàn toàn không làm gì khác ngoài việc trả về đường dẫn mà tệp sẽnếu nó tồn tại. Nó không thay đổi hệ thống tệp; nếu tệp không tồn tại, nó vẫn trả về Chuỗi đường dẫn và không tạo tệp. Ý bạn là gì khi "xem điều gì sẽ xảy ra"?
Bohemian

1
Filekhông phải là trận chung kết trong OpenJDK 7 của tôi
Dzmitry Lazerka

6

Jimfs , của Google, là một hệ thống tệp NIO trong bộ nhớ, rất tốt cho các thử nghiệm.


4

Một cách đơn giản là sử dụng cách hệ thống của bạn cung cấp một hệ thống tệp hoàn toàn dựa trên RAM - tempfs trên Linux, một đĩa RAM trên Windows.


Tôi không thấy điều đó sẽ tốt hơn như thế nào so với việc sử dụng hệ thống tệp thực (ngoài tốc độ).
elysium nuốt chửng vào

Vâng, tốc độ (và độ mòn đĩa) sẽ là lý do chính. Xin lỗi, có lẽ tôi đã hiểu sai mục tiêu của bạn.
Paŭlo Ebermann

1
Mục tiêu của tôi là dễ dàng thử nghiệm của tôi. Tôi hiện không quan tâm đến hiệu suất.
devoured elysium

4

MockFTPServer dường như có một vài triển khai Hệ thống tệp giả mạo (Unix / Windows)

Có vẻ như bạn có thể sử dụng các triển khai hệ thống tệp giả mạo này khá tách biệt với bất kỳ khái niệm FTP nào. Tôi đang thử điều này ngay bây giờ cho chính xác những mục tiêu giống như bạn đã vạch ra.


Tôi đang sử dụng UnixFakeFileSystem. Hoạt động rất tốt như một triển khai giả cho sự trừu tượng hóa FileSystem của tôi.
Deano

2

Tôi không chắc chắn về các khuôn khổ cụ thể, nhưng cách tiếp cận chung về OOP là viết một số lớp trừu tượng lên trên bất kỳ mã truy cập tệp nào (giao diện rất nhiều!) và có lẽ là một mặt tiền để dễ sử dụng các hoạt động thông thường. sau đó bạn chỉ mô phỏng một lớp bên dưới mã bạn đang thử nghiệm và về cơ bản nó là một hệ thống tệp giả mạo (hoặc ít nhất là mã bạn đang thử nghiệm sẽ không biết).

nếu bạn xem xét việc sử dụng khung phụ thuộc để xử lý điều này cho bạn, nó sẽ dễ dàng chuyển đổi các thành phần để triển khai giả mạo một giao diện. nếu bạn tuân theo các mẫu điều khiển nghịch đảo, việc chuyển bất kỳ phần phụ thuộc nào vào phương thức khởi tạo của lớp mà bạn đang kiểm tra, điều này cũng sẽ giúp dễ dàng kiểm tra.

public interface IFileSystem {
   IFileHandle Load(string path);
   //etc
}

public class ClassBeingTested {
   public ClassBeingTested(IFileSystem fileSystem) {
      //assign to private field
   }

   public void DoSomethingWithFileSystem() {
       //utilise interface to file system here
       //which you could easily mock for testing purposes
       //by passing a fake implementation to the constructor
   }
}

tôi hy vọng java của tôi là chính xác, tôi đã không viết java trong một thời gian dài, nhưng bạn sẽ có được sự trôi chảy. hy vọng rằng tôi không đánh giá thấp vấn đề ở đây và quá đơn giản hóa!

tất nhiên điều này chỉ là giả định bạn muốn nói đến kiểm thử đơn vị thực sự, tức là kiểm tra các đơn vị mã nhỏ nhất có thể, chứ không phải toàn bộ hệ thống. để kiểm tra tích hợp, một cách tiếp cận khác là cần thiết.


1
Một hệ thống tệp giả cần phải có logic của riêng nó - đó là một hệ thống tệp giống như bất kỳ hệ thống tệp nào khác, nhưng nó chỉ tồn tại trong bộ nhớ. Tôi muốn tránh phải tự lập trình một hệ thống tệp như vậy.
devoured elysium

bạn đang muốn bắt chước loại hoạt động hệ thống tệp nào? khóa tệp? đọc viết? hoặc những thứ đơn giản như mở tệp, kiểm tra thư mục tồn tại, tạo tệp?
WickyNilliams

Chủ yếu là các thao tác đơn giản nhằm kiểm tra xem tệp là tệp hay thư mục, nếu chúng tồn tại, để tạo tệp, xóa tệp. Điều này, tất nhiên, trong khi hỗ trợ nhiều thư mục và các hoạt động như "lấy đường dẫn từ tên tập tin này", "lấy đường dẫn tương đối từ các đường dẫn tuyệt đối", vv
Elysium nuốt

Tôi nghĩ như tôi đã nói, tạo ra một phản ứng xung quanh hệ thống tệp vật lý và luôn sử dụng nó (luôn mã hóa giao diện) trong suốt ứng dụng của bạn. sau đó chỉ cần sử dụng phương pháp tiêm phụ thuộc để đưa ra thông qua đối tượng thử nghiệm của bạn. tôi biết nó là một công việc đơn điệu nhưng khi lập trình chúng ta phải làm những việc này để đạt được một tách sạch các mối quan tâm và cho phép dễ testability :)
WickyNilliams

Bạn thực sự không hiểu những gì đang được yêu cầu ở đây. Nếu tôi đang tìm kiếm một hệ thống tệp giả mạo, đó phải là vì tôi đã tạo một bản tóm tắt toàn bộ hệ thống tệp trong ứng dụng của mình (như đã nêu trong nhận xét của OP). Tôi chỉ cần một cài đặt giả của hệ thống tập tin để sử dụng trong các thử nghiệm của tôi ..
Elysium nuốt

2

ShrinkWrap từ dự án Arquillian dường như bao gồm tuân thủ NIO trong FileSystem bộ nhớ

Bạn có thể tạo một FileSystem đơn giản trong bộ nhớ bằng cách làm như sau:

FileSystem fs = ShrinkWrapFileSystems.newFileSystem(ShrinkWrap.create(GenericArchive.class))

Liệu nó hỗ trợ file: // giao thức, không thể tìm thấy tài liệu ....
Marco Vasapollo


0

Tôi đã tìm kiếm "Hệ thống tệp java giả mạo" và tìm thấy câu hỏi này. Thật không may, đây là tất cả những gì tôi tìm thấy. Vì vậy, tôi đã tự viết FileSystem giả mạo này: https://github.com/dernasherbrezon/mockfs

Tôi đang sử dụng nó để mô phỏng IOExceptions trong quá trình đọc / ghi vào tệp. IOException có thể xảy ra chẳng hạn do "không có dung lượng đĩa", điều này gần như không thể mô phỏng bằng các phương tiện khác.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.