Mocking là gì? .
Mocking là gì? .
Câu trả lời:
Lời mở đầu: Nếu bạn tra cứu danh từ giả trong từ điển, bạn sẽ thấy rằng một trong những định nghĩa của từ này là một cái gì đó được làm như một sự bắt chước .
Mocking chủ yếu được sử dụng trong thử nghiệm đơn vị. Một đối tượng được thử nghiệm có thể có sự phụ thuộc vào các đối tượng (phức tạp) khác. Để cô lập hành vi của đối tượng bạn muốn thay thế các đối tượng khác bằng các mô phỏng mô phỏng hành vi của các đối tượng thực. Điều này rất hữu ích nếu các đối tượng thực tế là không thực tế để kết hợp vào bài kiểm tra đơn vị.
Nói tóm lại, chế giễu là tạo ra các đối tượng mô phỏng hành vi của các đối tượng thực.
Đôi khi bạn có thể muốn phân biệt giữa chế giễu trái ngược với gốc cây . Có thể có một số bất đồng về chủ đề này nhưng định nghĩa của tôi về sơ khai là một đối tượng mô phỏng "tối thiểu". Sơ khai thực hiện hành vi vừa đủ để cho phép đối tượng được thử nghiệm thực hiện thử nghiệm.
Một bản giả giống như một sơ khai nhưng bài kiểm tra cũng sẽ xác minh rằng đối tượng được kiểm tra gọi bản giả như mong đợi. Một phần của bài kiểm tra là xác minh rằng giả được sử dụng đúng.
Để đưa ra một ví dụ: Bạn có thể khai thác cơ sở dữ liệu bằng cách triển khai cấu trúc trong bộ nhớ đơn giản để lưu trữ các bản ghi. Đối tượng được kiểm tra sau đó có thể đọc và ghi các bản ghi vào sơ đồ cơ sở dữ liệu để cho phép nó thực hiện kiểm tra. Điều này có thể kiểm tra một số hành vi của đối tượng không liên quan đến cơ sở dữ liệu và sơ khai cơ sở dữ liệu sẽ được đưa vào chỉ để cho phép chạy thử.
Thay vào đó, nếu bạn muốn xác minh rằng đối tượng được kiểm tra ghi một số dữ liệu cụ thể vào cơ sở dữ liệu, bạn sẽ phải giả định cơ sở dữ liệu. Thử nghiệm của bạn sau đó sẽ kết hợp các xác nhận về những gì được ghi vào cơ sở dữ liệu giả.
Các câu trả lời khác giải thích mocking là gì. Hãy để tôi hướng dẫn bạn qua nó với các ví dụ khác nhau . Và tin tôi đi, nó thực sự đơn giản hơn nhiều so với bạn nghĩ.
tl; dr Đó là một thể hiện của lớp gốc. Nó có dữ liệu khác tiêm vào, do đó bạn tránh thử nghiệm những phần tiêm và chỉ tập trung vào kiểm tra chi tiết thực hiện các lớp học của bạn / chức năng.
Một ví dụ đơn giản:
class Foo {
func add (num1: Int, num2: Int) -> Int { // Line A
return num1 + num2 // Line B
}
}
let unit = Foo() // unit under test
assertEqual(unit.add(1,5),6)
Như bạn có thể thấy, tôi không kiểm tra LineA tức là tôi không xác thực các tham số đầu vào. Tôi không xác thực để xem nếu num1, num2 là một số nguyên. Tôi không có khẳng định chống lại điều đó.
Tôi chỉ đang thử nghiệm để xem LineB ( triển khai của tôi ) có đưa ra các giá trị bị chế giễu 1
hay không và 5
đang làm như tôi mong đợi.
Rõ ràng trong từ thực sự điều này có thể trở nên phức tạp hơn nhiều. Các tham số có thể là một đối tượng tùy chỉnh như Người, Địa chỉ hoặc chi tiết triển khai có thể nhiều hơn một +
. Nhưng logic của thử nghiệm sẽ giống nhau.
Giả sử bạn đang xây dựng một máy xác định loại và tên thương hiệu của các thiết bị điện tử để bảo mật sân bay. Máy thực hiện điều này bằng cách xử lý những gì nó nhìn thấy bằng camera của nó.
Bây giờ người quản lý của bạn bước vào cửa và yêu cầu bạn kiểm tra đơn vị.
Sau đó, với tư cách là nhà phát triển, bạn có thể mang 1000 đối tượng thực, như MacBook pro, Google Nexus, chuối, iPad, v.v. ra trước nó và kiểm tra xem tất cả có hoạt động không.
Nhưng bạn cũng có thể sử dụng các đối tượng bị chế giễu , như một chiếc MacBook pro trông giống hệt (không có bộ phận bên trong thực sự) hoặc một quả chuối nhựa phía trước nó. Bạn có thể tiết kiệm cho mình từ việc đầu tư vào năm 1000 máy tính xách tay thực tế và mục nát chuối.
Vấn đề là bạn không cố gắng để kiểm tra nếu chuối là giả hay không. Cũng không kiểm tra xem laptop có giả hay không. Tất cả những gì bạn đang làm là kiểm tra xem máy của bạn một khi nó nhìn thấy một quả chuối thì nó sẽ nói not an electronic device
và đối với MacBook Pro thì nó sẽ nói : Laptop, Apple
. Đối với máy, kết quả phát hiện của nó phải giống với điện tử giả / giả và điện tử thật
Logic được đề cập ở trên cũng áp dụng cho kiểm thử đơn vị mã thực tế. Đó là một hàm nên hoạt động tương tự với các giá trị thực bạn nhận được từ đầu vào thực (và tương tác) hoặc bị chế giễugiá trị bạn tiêm trong đơn vị thử nghiệm. Và cũng giống như cách bạn tự cứu mình khỏi việc sử dụng chuối hoặc MacBook thực sự, với các bài kiểm tra đơn vị (và chế giễu), bạn tự cứu mình khỏi phải làm điều gì đó khiến máy chủ của bạn trả lại mã trạng thái 500, 403, 200, v.v. Máy chủ của bạn để kích hoạt 500 chỉ khi máy chủ ngừng hoạt động, trong khi 200 là khi máy chủ hoạt động. Thật khó để chạy 100 bài kiểm tra tập trung vào mạng nếu bạn phải liên tục chờ 10 giây giữa chuyển đổi lên và xuống máy chủ). Vì vậy, thay vào đó bạn tiêm / giả một phản hồi với mã trạng thái 500, 200, 403, v.v. và kiểm tra đơn vị / chức năng của bạn với giá trị được tiêm / giả.
Giả sử bạn đang viết một ứng dụng iOS và có các cuộc gọi mạng. Công việc của bạn là kiểm tra ứng dụng của bạn . Để kiểm tra / xác định xem các cuộc gọi mạng có hoạt động như mong đợi KHÔNG PHẢI LÀ TRÁCH NHIỆM CỦA BẠN. Trách nhiệm của một bên khác (nhóm máy chủ) là kiểm tra nó. Bạn phải loại bỏ sự phụ thuộc (mạng) này và tiếp tục kiểm tra tất cả mã của bạn hoạt động xung quanh nó.
Một cuộc gọi mạng có thể trả về các mã trạng thái khác nhau 404, 500, 200, 303, v.v với phản hồi JSON.
Ứng dụng của bạn được cho là hoạt động cho tất cả chúng (trong trường hợp có lỗi, ứng dụng của bạn sẽ ném lỗi dự kiến). Những gì bạn làm với chế độ chế giễu là bạn tạo ra 'tưởng tượng' tương tự như các phản hồi mạng thực '(như mã 200 với tệp JSON) và kiểm tra mã của bạn mà không ' thực hiện cuộc gọi mạng thực và chờ phản hồi mạng của bạn '. Bạn mã hóa thủ công / trả lại phản hồi mạng cho TẤT CẢ các loại phản hồi mạng và xem ứng dụng của bạn có hoạt động như bạn mong đợi không. (bạn không bao giờ giả định / kiểm tra 200 với dữ liệu không chính xác, vì đó không phải là trách nhiệm của bạn, trách nhiệm của bạn là kiểm tra ứng dụng của bạn với 200 chính xác hoặc trong trường hợp 400, 500, bạn kiểm tra xem ứng dụng của bạn có đưa ra lỗi đúng không)
Điều này tạo ra trí tưởng tượng tương tự như thực tế được gọi là chế nhạo.
Để thực hiện việc này, bạn không thể sử dụng mã gốc của mình (mã gốc của bạn không có phản hồi được chèn sẵn, phải không?). Bạn phải thêm một cái gì đó vào nó, tiêm / chèn dữ liệu giả đó thường không cần thiết (hoặc một phần của lớp học của bạn).
Vì vậy, bạn tạo một thể hiện của lớp gốc và thêm bất cứ thứ gì (ở đây là HTTPResponse mạng, dữ liệu HOẶC trong trường hợp không thành công, bạn chuyển đúng errorString, HTTPResponse) bạn cần đến nó và sau đó kiểm tra lớp bị giả .
Câu chuyện dài, chế giễu là để đơn giản hóa và giới hạn những gì bạn đang kiểm tra và cũng khiến bạn nuôi những gì một lớp học phụ thuộc vào. Trong ví dụ này, bạn tránh kiểm tra các cuộc gọi mạng mình , và thay vào đó kiểm tra hay không ứng dụng của bạn hoạt động như bạn mong đợi với những kết quả tiêm / phản ứng - do chế giễu lớp
Không cần phải nói, bạn kiểm tra từng phản ứng mạng riêng biệt.
Bây giờ một câu hỏi mà tôi luôn có trong đầu là: Các hợp đồng / điểm kết thúc và về cơ bản là phản hồi JSON của các API của tôi được cập nhật liên tục. Làm thế nào tôi có thể viết bài kiểm tra đơn vị mà xem xét điều này?
Để giải thích rõ hơn về điều này: giả sử mô hình yêu cầu khóa / trường có tên username
. Bạn kiểm tra điều này và bài kiểm tra của bạn vượt qua. 2 tuần sau, phụ trợ thay đổi tên của khóa thành id
. Bài kiểm tra của bạn vẫn vượt qua. đúng? hay không?
Có phải là trách nhiệm của nhà phát triển phụ trợ để cập nhật các bản giả. Có nên là một phần trong thỏa thuận của chúng tôi rằng họ cung cấp các bản giả được cập nhật?
Câu trả lời cho vấn đề trên là: kiểm tra đơn vị + quy trình phát triển của bạn với tư cách là nhà phát triển phía khách hàng sẽ / sẽ bắt được phản hồi giả định lỗi thời. Nếu bạn hỏi tôi như thế nào? câu trả lời là:
Ứng dụng thực tế của chúng tôi sẽ thất bại (hoặc không thất bại nhưng không có hành vi mong muốn) nếu không sử dụng API cập nhật ... do đó nếu thất bại ... chúng tôi sẽ thay đổi mã phát triển của mình. Điều này một lần nữa dẫn đến các thử nghiệm của chúng tôi thất bại .... mà chúng tôi sẽ phải sửa nó. (Trên thực tế nếu chúng ta thực hiện đúng quy trình TDD, chúng ta sẽ không viết bất kỳ mã nào về trường trừ khi chúng ta viết thử nghiệm cho nó ... và thấy nó thất bại và sau đó đi và viết mã phát triển thực tế cho nó.)
Tất cả điều này có nghĩa là phụ trợ không cần phải nói: đó là chúng tôi đã cập nhật các bản nháp ... cuối cùng nó cũng xảy ra thông qua việc phát triển / gỡ lỗi mã của bạn. Bởi vì đó là một phần của quá trình phát triển! Mặc dù nếu phụ trợ cung cấp phản hồi giả cho bạn thì điều đó dễ dàng hơn.
Toàn bộ quan điểm của tôi về vấn đề này là (nếu bạn không thể tự động nhận được cập nhật phản ứng API chế giễu rồi) một số tương tác của con người là cần thiết tức là tay bản cập nhật của JSONs và có cuộc họp ngắn để đảm bảo giá trị của họ được cập nhật sẽ trở thành một phần của quá trình của bạn
Phần này được viết nhờ vào một cuộc thảo luận chậm chạp trong nhóm gặp gỡ của chúng tôi
Chỉ dành cho nhà phát triển iOS:
Một ví dụ rất hay về chế giễu là bài nói chuyện theo định hướng Giao thức thực tế này của Natasha Muraschev . Chỉ cần bỏ qua đến phút 18:30, mặc dù các slide có thể không đồng bộ với video thực tế
Tôi thực sự thích phần này từ bảng điểm:
Bởi vì đây là thử nghiệm ... chúng tôi muốn đảm bảo rằng
get
chức năng từGettable
được gọi, bởi vì nó có thể trở lại và về mặt lý thuyết chức năng có thể gán một mảng các mặt hàng thực phẩm từ bất cứ đâu . Chúng ta cần đảm bảo rằng nó được gọi;
Có rất nhiều câu trả lời về SO và những bài viết hay trên web về chế giễu. Một nơi mà bạn có thể muốn bắt đầu tìm kiếm là bài đăng của Martin Fowler Mocks Ar't Stub nơi ông thảo luận về rất nhiều ý tưởng chế giễu.
Trong một đoạn - Mocking là một kỹ thuật chi tiết để cho phép thử nghiệm một đơn vị mã mà không phụ thuộc vào các phụ thuộc. Nói chung, điểm khác biệt của việc nhạo báng với các phương thức khác là các đối tượng giả được sử dụng để thay thế phụ thuộc mã sẽ cho phép đặt kỳ vọng - một đối tượng giả sẽ biết cách gọi mã của bạn và cách phản hồi.
Câu hỏi ban đầu của bạn đã đề cập đến TypeMock, vì vậy tôi đã để lại câu trả lời của mình cho câu hỏi dưới đây:
TypeMock là tên của một khung mô phỏng thương mại .
Nó cung cấp tất cả các tính năng của các khung mô phỏng miễn phí như RhinoMocks và Moq, cùng với một số tùy chọn mạnh mẽ hơn.
Cho dù bạn có cần TypeMock hay không vẫn còn gây tranh cãi - bạn có thể thực hiện hầu hết các chế độ chế giễu mà bạn muốn với các thư viện chế giễu miễn phí, và nhiều ý kiến cho rằng các khả năng do TypeMock cung cấp thường sẽ đưa bạn ra khỏi thiết kế được đóng gói tốt.
Như một câu trả lời khác đã nêu 'TypeMocking' thực sự không phải là một khái niệm xác định, nhưng có thể được hiểu là kiểu chế nhạo mà TypeMock đưa ra, sử dụng trình lược tả CLR để chặn .Net gọi trong thời gian chạy, mang lại khả năng lớn hơn cho các đối tượng giả (không phải yêu cầu chẳng hạn như cần giao diện hoặc phương thức ảo).
Mock là một phương thức / đối tượng mô phỏng hành vi của một phương thức / đối tượng thực theo các cách được kiểm soát. Đối tượng giả được sử dụng trong thử nghiệm đơn vị.
Thường thì một phương thức trong một thử nghiệm gọi các dịch vụ hoặc phương thức bên ngoài khác trong đó. Chúng được gọi là phụ thuộc. Sau khi bị chế giễu, các phụ thuộc hành xử theo cách chúng ta định nghĩa chúng.
Với sự phụ thuộc được kiểm soát bởi các giả, chúng ta có thể dễ dàng kiểm tra hành vi của phương thức mà chúng ta đã mã hóa. Đây là bài kiểm tra đơn vị.
Mục đích của các loại chế nhạo là cắt đứt các phụ thuộc để cô lập thử nghiệm với một đơn vị cụ thể. Sơ khai là những người thay thế đơn giản, trong khi giả là người thay thế có thể xác minh việc sử dụng. Khung mô phỏng là một công cụ sẽ giúp bạn tạo ra các sơ khai và giả.
EDIT : Kể từ khi từ ngữ ban đầu đề cập đến "kiểu nhạo báng", tôi có ấn tượng rằng điều này liên quan đến TypeMock. Theo kinh nghiệm của tôi các thuật ngữ chung chỉ là "chế giễu". Xin vui lòng bỏ qua thông tin dưới đây cụ thể trên TypeMock.
TypeMock Isolator khác với hầu hết các khung mô phỏng khác ở chỗ nó hoạt động việc sửa đổi IL của tôi một cách nhanh chóng. Điều đó cho phép nó giả định các loại và trường hợp mà hầu hết các khung công tác khác không thể giả định. Để chế nhạo các loại / trường hợp này với các khung khác, bạn phải cung cấp các tóm tắt của riêng bạn và giả định các kiểu này.
TypeMock cung cấp tính linh hoạt cao với chi phí của môi trường thời gian chạy sạch. Là một tác dụng phụ của cách TypeMock đạt được kết quả của nó, đôi khi bạn sẽ nhận được kết quả rất lạ khi sử dụng TypeMock.
Tôi nghĩ rằng việc sử dụng khung mô phỏng bộ cách ly TypeMock sẽ là TypeMocking.
Nó là một công cụ tạo ra các giả để sử dụng trong các bài kiểm tra đơn vị, mà không cần phải viết mã của bạn với IoC trong tâm trí.
Nếu giả của bạn liên quan đến một yêu cầu mạng, một lựa chọn khác là có một máy chủ thử nghiệm thực sự để đánh. Bạn có thể sử dụng dịch vụ này để tạo yêu cầu và phản hồi cho thử nghiệm của mình. http://testerurl.com/