2010-01-30 32 views
17

Tôi có một singleton độc lập đã vượt qua thành công bài kiểm tra. Nhưng với một nhóm các bài kiểm tra này không thành công kể từ khi một singleton được định nghĩa nó không cho phép thiết lập lại cá thể.Các trường hợp Singleton khác nhau với các bài kiểm tra JUnit

Bất kỳ ý tưởng nào về cách thực hiện việc này?

Trả lời

9

Không sử dụng singleton.

Cụ thể, sự khác biệt duy nhất giữa một biến đơn và biến toàn cầu là singleton cố gắng thực thi một cá thể đơn lẻ (ví dụ như tạo hàm tạo riêng).

Thay vào đó, hãy đặt hàm tạo công khai và viết kiểm tra bằng các phiên bản mới. Trong chương trình thực tế của bạn, hãy sử dụng getInstance() để có được cá thể chung toàn cầu (hoặc sử dụng một thùng chứa IOC).

Và hãy nhớ rằng singletons are pathological liars.

Nếu bạn vẫn còn quá thoải mái với ý tưởng về Singleton, thay vì đặt công khai hàm tạo, bạn có thể thêm phương thức nhà máy công cộng (và tĩnh) để tạo các cá thể theo cách không thể sử dụng do tai nạn, ví dụ:

public static MyClass TEST_CreateInstance() { 
    return new MyClass(); 
} 
3

Bạn có thể thêm phương thức để hủy đơn lẻ, ví dụ: destroyMe(); nơi bạn deinitialize tất cả mọi thứ và thiết lập các trường hợp của singleton để null.

public void destroyMe(){ 
    this.instance = null; 
    //-- other stuff to turn it off. 
} 

tôi sẽ để lại vấn đề đồng bộ hóa mặc dù;)

Nhưng tại sao bạn cần để tái khởi singleton của bạn cho mỗi thử nghiệm? Nó không nên khác nhau dựa trên khái niệm của singleton.

10

Tôi giả sử bạn có một trường tĩnh riêng trong lớp singleton của bạn để lưu trữ cá thể khởi tạo.

Nếu bạn không muốn sửa đổi mã của mình, bạn có thể xác định phương pháp ngăn chặn chạy sau mỗi lần kiểm tra và trong phương pháp này, bạn đặt trường tĩnh thành giá trị rỗng qua phản ánh như được thấy here.

+1

-1, IMO điều này làm cho tình huống xấu trở nên tồi tệ hơn – orip

+13

+1 để đưa ra giải pháp thực tế. Tôi không có quyền kiểm soát mã của bên thứ ba, đó là một singleton, và có một nhu cầu cho các giải pháp, không nên làm thế nào nó nên được thực hiện. – eis

1

thường cẩn thận với người độc thân, thường là thiết kế xấu, xấu và có xu hướng đại diện cho các biến toàn cầu yucky lớn (điều này không tốt cho việc bảo trì).

vẫn để có được kiểm tra ở nơi đầu tiên bạn có thể làm:

 

static setInstance(...){ //package visibility or in difficult cases you have to use public 
    instance = ...; 
} 
 

như đã nói ở đây là thêm một workaround. để có được các bài kiểm tra đầu tiên, nhưng sau đó refactor ra khỏi mô hình singleton.

0

Ví dụ Singleton cần được chuyển đến SUT bằng chính bản thân kiểm tra - theo cách đó bạn tạo singleton (và hủy) cho mỗi bài kiểm tra. Áp dụng IoC và khuôn khổ mocking, giống như Mockito, sẽ làm cho phương pháp này gần như tầm thường.

1

tôi khuyên di chuyển ra khỏi Singletons như một mẫu thiết kế, và sử dụng Singleton như một phạm vi (Dependency Injection). Điều này sẽ đơn giản làm cho vấn đề của bạn biến mất.

Nhưng giả sử bạn đang mắc kẹt trong thế giới của Singletons, sau đó bạn có một vài tùy chọn tùy thuộc vào nếu bạn đang thử nghiệm Singleton hoặc phụ thuộc.

Nếu bạn đang thử nghiệm mục phụ thuộc, bạn có thể thử Singleton sử dụng PowerMockJMockIt. Xem của tôi previous post về mocking Runtime.getRuntime để biết hướng dẫn về cách thực hiện việc này.

Nếu bạn đang thử nghiệm Singleton thì bạn cần phải thư giãn các quy tắc về xây dựng, hoặc cung cấp cho Singleton một phương pháp "Reset".

1

Mùa xuân cung cấp chú thích DirtiesContext cho trường hợp sử dụng cụ thể này khi bạn cần các phiên bản mới của hạt đơn cho mỗi testcase. Về cơ bản nó tạo ra một bối cảnh ứng dụng mới cho mỗi testcase/testclass có chú thích này được áp dụng.

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