2011-08-22 23 views
11

Câu hỏi hoàn chỉnh hơn là, với sự phụ thuộc kỳ vọng gọi lại làm tham số, làm cách nào để viết một bài kiểm tra đơn vị bao gồm logic gọi lại vẫn quản lý để giả lập phụ thuộc?Làm thế nào để đơn vị kiểm tra gọi lại logic?

public class DoStuff { 
    public void runThis(Runnable callback) { 
     // call callback 
    } 
} 

public class ClassUnderTest { 
    private DoStuff stuffToDo; 

    public void methodUnderTest() { 
     this.stuffToDo.runThis(/*a runnable with some logic*/) 
    } 
} 

Trong ví dụ trên, tôi sẽ thử stuffToDo vì tôi nên xác minh cuộc gọi và kết xuất đầu ra của cuộc gọi phương thức. Tuy nhiên, chế nhạo runThis kết quả trong logic gọi lại không được kiểm tra. Hơn nữa, gọi lại logic có vẻ như nó nên được tư nhân vì vậy tôi sẽ không mong đợi để kiểm tra nó trực tiếp; có lẽ đó là một quan niệm sai lầm về phía tôi.

Kể từ khi gọi lại được sử dụng khá rộng rãi, tôi hy vọng sẽ có một phương pháp phổ biến để thử nghiệm chúng nhưng tôi đã không tìm thấy nó.

+0

Cuộc gọi lại chỉ cần được kiểm tra trong ngữ cảnh này? Nếu vậy, tại sao không chỉ đơn giản là viết các bài kiểm tra cho các callbacks khác nhau mà bạn có kế hoạch đi qua, trong đó thể hiện mong đợi của bạn về kết quả của họ? Tui bỏ lỡ điều gì vậy? – Jonah

+0

Bạn đã thử sử dụng CountDownLatch giống như trong ví dụ này: http://stackoverflow.com/a/3802487/2301224 – Baker

Trả lời

10

Bạn không thể làm một thử nghiệm. Nếu bạn mô phỏng một cái gì đó, chế nhạo của nó, có nghĩa là nó chỉ có thể xác minh đối số và mô phỏng các giá trị trả lại (mà bạn định cấu hình trong thử nghiệm).

Thật vậy, toàn bộ điểm chế nhạo một cái gì đó là để kiểm tra những gì sử dụng giả trong sự cô lập. Nếu bạn muốn thử nghiệm đơn vị DoStuff, bạn không muốn phải lo lắng về việc sử dụng một số triển khai gọi lại có thể có hoặc không hoạt động. Bạn giả lập gọi lại để bạn không phải lo lắng về nó. Bạn có thể vẫn có các bài kiểm tra tốt bằng cách kiểm tra mã gọi lại một cách độc lập, kiểm tra người dùng gọi lại một cách riêng biệt (sử dụng mô hình gọi lại) và có thể bằng cách thử nghiệm tích hợp để có biện pháp tốt, nơi bạn sử dụng thành phần được cấu hình đầy đủ.

1

Ở đây về cơ bản bạn muốn kiểm tra lớp DoStuff. Điều đó có nghĩa là bạn cần phải kiểm tra tất cả các phương thức bên trong DoStuff, đúng không ?. Vì vậy, trong trường hợp này, những gì bạn cần làm là, thay vì chế nhạo stuffToDo chính nó, tiêm một Runnable giả lập thành stuffToDo. Và sau đó kiểm tra xem runnable của bạn đã được thực hiện thành công hay không.

Nhưng nếu bạn có các chức năng khác trong lớp học, bạn có thể có bài kiểm tra riêng và giả sử chúng.

+1

Tôi muốn kiểm tra ClassUnderTest nhận DoStuff dưới dạng phụ thuộc. –

0

Trong trường hợp cụ thể của bạn, có vẻ như bạn đã thử nghiệm DoStuff (hoặc không quan tâm nữa vì nó được chế nhạo) và bây giờ là thử nghiệm đơn vị cụ thể Runnable cụ thể mà bạn đã thiết kế. Trong trường hợp này, callback có vẻ giống như chính xác những gì bạn muốn thử nghiệm, giống như cách ai đó có thể muốn kiểm tra cụ thể một chiến lược cơ sở dữ liệu hoặc chiến lược trong bộ nhớ một cách trực tiếp.

Nếu đây là những gì bạn đang cố gắng, bạn có thể thử nghiệm nó trong một hộp đen, thực hiện nó thông qua ClassUnderTest nhất có thể. Hoặc bạn có thể tạo ra một thử nghiệm khai thác trên Runnable cụ thể của bạn. Nếu bạn đang phát hành mã này và không muốn làm cho khai thác thử nghiệm của bạn có thể truy cập, bạn có thể làm cho các phương pháp khai thác thử nghiệm riêng tư và chia sẻ chi tiết cụ thể với lắp ráp thử nghiệm đơn vị của bạn.

Nhìn here để biết thông tin về cách kết bạn. Tôi thường đăng ký mã kiểm tra đơn vị của mình để không phải muck với trình biên dịch dòng lệnh. Tôi cho rằng nó phụ thuộc vào môi trường xây dựng của bạn.

+0

Không, ClassUnderTest là lớp cần kiểm tra. Tôi đang chế giễu DoStuff. –

+0

Tôi đã sửa đổi tên lớp để phản ánh điều này. Nó không ảnh hưởng đến câu trả lời. –

0

Nếu bạn sử dụng EasyMock, bạn có thể sử dụng andStubAnswer để gọi runnable.

doSomethingMock.runThis(runnable); 
expectLastCall().andStubAnswer(new IAnserable<Void>() { 
    Runnable runnable = (Runnable)getCurrentArguments()[0]; 
    runnable.run(); 
    return null; 
}); 

Tôi tưởng tượng các khuôn khổ giả mạo khác chứa nội dung tương tự.

0

Làm thế nào về một DoStuff giả mạo mà chỉ cần gọi Runnable vô điều kiện?

Sau đó, bạn chỉ cảm nhận được các hiệu ứng - những thay đổi cần được quan sát nếu gọi lại của bạn đã được thực hiện.

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