Làm thế nào là các đối tượng giả thường được sử dụng sai?


15

Tôi đã đọc một bài báo gần đây nói rằng các đối tượng giả thường bị hiểu lầm và sử dụng sai. Có bất kỳ mô hình chống chế giễu rõ ràng nào mà tôi có thể tìm ra không?


là bài báo bạn đọc cái này? martinfowler.com/articles/mocksArentStub.html
keppla

không ... không thể nhớ chính xác nguồn nhưng sẽ đăng ở đây nếu tôi làm
Armand

Tôi đã được đưa vào nhiệm vụ trên stackoverflow để chế tạo API mongodb. Tôi đã được chỉ ra một bài đăng trên blog tuyên bố rằng nó sai khi chế giễu bất kỳ lớp nào mà chính bạn không viết. Tôi thực sự không đồng ý với điều này nhưng ý kiến ​​được đưa ra.
Kevin

Câu trả lời:


13

Tôi ghét nhìn thấy các lớp bê tông đơn giản chế giễu. Ví dụ, lấy lớp đơn giản sau đây không phụ thuộc vào bất cứ thứ gì khác:

public class Person
{
    private readonly string _firstName;
    private readonly string _surname;

    public Person(string firstName, string surname)
    {
        if (String.IsNullOrEmpty(firstName))
        {
            throw new ArgumentException("Must have first name");
        }

        if (String.IsNullOrEmpty(surname))
        {
            throw new ArgumentException("Must have a surname");
        }

        _firstName = firstName;
        _surname = surname;
    }

    public string Name 
    {
        get
        {
            return _firstName + " " + _surname;
        }
    }
}

Trong bất kỳ thử nghiệm nào liên quan đến lớp này, tôi thực sự muốn sử dụng một giao diện thực tế hơn là một giao diện như 'IPerson', một giao diện bị chế giễu được sử dụng và kỳ vọng được đặt ra. Bằng cách sử dụng thực tế, thử nghiệm của bạn thực tế hơn (bạn có kiểm tra tham số tại chỗ và triển khai thực sự của thuộc tính 'Tên'). Đối với một lớp đơn giản như thế này, bạn không làm cho các bài kiểm tra của mình chậm hơn, ít xác định hoặc làm rối logic (bạn không cần phải biết rằng Tên được gọi khi kiểm tra một số lớp khác) - đó là những lý do thông thường để chế nhạo / sơ khai.

Là một phần mở rộng cho điều này, tôi cũng đã thấy mọi người viết các bài kiểm tra trong đó bản giả được thiết lập với một kỳ vọng, sau đó bản giả được gọi trực tiếp trong bài kiểm tra. Không ngờ, bài kiểm tra sẽ luôn vượt qua ... hmmmm ...


Rất may là các khung mô phỏng mà tôi đã sử dụng đã có thể chế nhạo các lớp cụ thể, do đó, việc rút ra các giao diện tại các điểm bất tiện không phải là vấn đề.
Armand

5
Điều đó không làm thay đổi vấn đề - loại điều đơn giản này thường không bị chế giễu ngay cả khi bạn đang sử dụng thứ gì đó giúp giảm bớt các hạn chế kỹ thuật đối với những gì có thể bị chế giễu (ví dụ: khung giả định như TypeMock hoặc ngôn ngữ động).
FinnNk

Quy tắc ngón tay cái của tôi luôn luôn bị chế giễu vì hành vi, không phải vì dữ liệu.
ardave

10

Nghe có vẻ hiển nhiên, nhưng: Đừng sử dụng các đối tượng giả trong mã sản xuất! Tôi đã thấy nhiều hơn một ví dụ trong đó mã sản xuất phụ thuộc vào đặc điểm của các đối tượng giả nhất định ( MockHttpServletRequeství dụ từ Springframework).


14
Tôi hy vọng bạn tuân theo nghĩa vụ thánh của mình và gửi mã đến DailyWTF?
keppla

1
Trong công việc trước đây của chúng tôi, chúng tôi đã tuyệt đối cấm gửi bất cứ điều gì từ cơ sở mã của chúng tôi đến DWTF.
quant_dev

9
@quant_dev: Việc họ có chính sách như vậy ngụ ý những điều đáng sợ về các nhà phát triển của họ ...
John Fisher

1
Không hẳn vậy. Đó là một startup phải nhanh chóng phát triển một codebase để bán sản phẩm, sau đó bắt đầu hợp nhất và tái cấu trúc nó để trả nợ kỹ thuật, khi sản phẩm trưởng thành và phát triển hơn nữa bị cản trở bởi thiết kế ban đầu (thiếu). Các nhà quản lý biết rằng cơ sở mã cũ là rác rưởi, và đầu tư thời gian và nguồn lực vào tái cấu trúc, nhưng không muốn mạo hiểm với bất kỳ dư luận bất lợi nào.
quant_dev

Chỉ cần sử dụng các phím tắt không thực sự đủ để giúp bạn chỉ hàng ngày ...
poolie

9

Theo tôi đó là kiểm tra lời mời phương thức quá mức trên các giả. Tôi cảm thấy rằng đây là một thực tiễn được thi hành bởi một vài khung mô phỏng như EasyMock, trong đó hành vi giả định mặc định sẽ thất bại bất cứ khi nào có một lời gọi phương thức bổ sung mà trước đó không được chỉ định chính xác. Kiểu kiểm tra phương pháp giả nghiêm ngặt này có thể dẫn đến các thiết kế dễ vỡ trong đó việc thay đổi mã nhỏ nhất có thể dẫn đến toàn bộ các thử nghiệm thất bại, mặc dù chức năng cốt lõi vẫn giống nhau.

Một giải pháp cho vấn đề này là bắt đầu sử dụng sơ khai thay vì giả. Một bài viết mà tôi thấy đặc biệt khai sáng về chủ đề này được tìm thấy trong Mockito's Javadoc: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html (xem "2. Làm thế nào về một số sơ khai?" ), liên kết đến: http://monkeyisland.pl/2008/07/12/should-i-w lỗi-about-the-unazed / .

Cho đến nay, tôi rất thích làm việc với Mockito vì nó không thực thi hành vi chế giễu nghiêm ngặt này mà thay vào đó là sử dụng cuống. Nó cũng thực thi kiểm tra phương thức trên những cái cụ thể thay vì toàn bộ đối tượng giả; Vì vậy, bạn cuối cùng chỉ kiểm tra các phương pháp thực sự quan trọng trong kịch bản thử nghiệm của bạn.

Có một vài cuốn sách ở đây và ở đó tôi có thể khuyên bạn nên chạm vào chủ đề này và chế giễu và chung chung:

mẫu xUnit

Nghệ thuật kiểm tra đơn vị: Với các ví dụ trong .Net

Thử nghiệm Java thế hệ tiếp theo: TestNG và các khái niệm nâng cao (cuốn sách này chủ yếu nói về testNG nhưng có một chương hay về chế giễu)


+1 cho điểm trên kiểm tra gọi phương thức quá mức. Tuy nhiên, luôn có mặt trái của đồng xu trong đó việc gọi phương thức không mong muốn gây ra lỗi trong phương thức của bạn. Rất may, Mockito có Answer.RETURNS_SMART_NULLScài đặt cho các giả giúp chẩn đoán điều này.
Bringer128

4

Tôi đã quan sát thấy một số chống mẫu trong kinh nghiệm của tôi.

  • Các lớp miền bị chế giễu / sơ khai nơi thay đổi trạng thái có thể xảy ra và điều đó cần được xác minh.
  • Các thử nghiệm tích hợp tương tác với một hỗn hợp các giả và các lớp cụ thể đánh bại mục đích của các thử nghiệm tích hợp.
  • Vô tình sử dụng giả trong mã sản xuất (Điều này không bao giờ nên xảy ra)

Nếu không, kinh nghiệm của tôi với các giả, đặc biệt là Mockito đã được dễ dàng. Họ đã thực hiện các bài kiểm tra rất dễ dàng để viết và duy trì. Kiểm tra tương tác của người xem / người trình bày của GWT dễ dàng hơn nhiều với các giả so với GWTTestCase.


2 & 3 là những vấn đề nhất định! Bạn đã có một ví dụ đơn giản về (1)?
Armand

2

Tôi thấy rằng các bài kiểm tra sử dụng giả trên nhiều lớp của một ứng dụng đặc biệt khó giải mã và thay đổi. Tuy nhiên, tôi nghĩ rằng điều này đã được giảm nhẹ trong những năm gần đây bằng cách cải thiện API của khung công tác giả (Tôi sử dụng JMock khi thuận tiện).

5 hoặc 6 năm trước, các API như EasyMock rất mạnh mẽ nhưng rất cồng kềnh. Thông thường mã kiểm tra sử dụng nó là các đơn đặt hàng có độ lớn phức tạp hơn mã mà nó đang kiểm tra. Trước đó, tôi đã cố gắng gây ảnh hưởng đến các đội mà tôi tham gia để sử dụng nó một cách tiết kiệm và thực hiện với các mô phỏng thủ công đơn giản chỉ đơn giản là thực hiện xen kẽ các giao diện để thử nghiệm.

Gần đây, những ý kiến ​​mạnh mẽ của tôi về điều này đã trở nên nhẹ nhàng hơn khi các API chế giễu đã thực hiện các bài kiểm tra sử dụng chúng dễ đọc hơn. Về cơ bản, tôi muốn mã của tôi (bao gồm các bài kiểm tra) có thể được thay đổi bởi các nhà phát triển khác mà không khiến họ cảm thấy như họ đang lọc qua một loạt các lệnh gọi API tối nghĩa.

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.