RSpec - Kiểm tra gấp đôi
Trong chương này, chúng ta sẽ thảo luận về RSpec Double, còn được gọi là RSpec Mocks. Double là một đối tượng có thể “đứng trong” đối tượng khác. Bạn có thể tự hỏi điều đó chính xác có nghĩa là gì và tại sao bạn cần một cái.
Giả sử bạn đang xây dựng ứng dụng cho một trường học và bạn có một lớp đại diện cho một lớp học của sinh viên và một lớp khác dành cho sinh viên, nghĩa là bạn có lớp Lớp học và lớp Sinh viên. Trước tiên, bạn cần viết mã cho một trong các lớp học, vì vậy hãy nói rằng, hãy bắt đầu với lớp Lớp học -
class ClassRoom
def initialize(students)
@students = students
end
def list_student_names
@students.map(&:name).join(',')
end
end
Đây là một lớp đơn giản, nó có một phương thức list_student_names, trả về một chuỗi tên sinh viên được phân tách bằng dấu phẩy. Bây giờ, chúng ta muốn tạo các bài kiểm tra cho lớp này nhưng làm thế nào để làm điều đó nếu chúng ta chưa tạo lớp Sinh viên? Chúng tôi cần một bài kiểm tra Double.
Ngoài ra, nếu chúng ta có một lớp “dummy” hoạt động như một đối tượng Sinh viên thì các bài kiểm tra ClassRoom của chúng ta sẽ không phụ thuộc vào lớp Sinh viên. Chúng tôi gọi đây là sự cô lập thử nghiệm.
Nếu các bài kiểm tra ClassRoom của chúng tôi không dựa trên bất kỳ lớp nào khác, thì khi kiểm tra không thành công, chúng tôi có thể biết ngay rằng có lỗi trong lớp ClassRoom của chúng tôi chứ không phải một số lớp khác. Hãy nhớ rằng, trong thế giới thực, bạn có thể đang xây dựng một lớp cần tương tác với một lớp khác do người khác viết.
Đây là lúc RSpec Double (mocks) trở nên hữu ích. Phương thức list_student_names của chúng tôi gọi phương thức name trên mỗi đối tượng Student trong biến thành viên @students của nó. Do đó, chúng ta cần một Double thực hiện một phương thức tên.
Đây là mã cho ClassRoom cùng với Ví dụ RSpec (thử nghiệm), nhưng lưu ý rằng không có lớp Sinh viên nào được xác định -
class ClassRoom
def initialize(students)
@students = students
end
def list_student_names
@students.map(&:name).join(',')
end
end
describe ClassRoom do
it 'the list_student_names method should work correctly' do
student1 = double('student')
student2 = double('student')
allow(student1).to receive(:name) { 'John Smith'}
allow(student2).to receive(:name) { 'Jill Smith'}
cr = ClassRoom.new [student1,student2]
expect(cr.list_student_names).to eq('John Smith,Jill Smith')
end
end
Khi đoạn mã trên được thực thi, nó sẽ tạo ra kết quả sau. Thời gian đã trôi qua có thể hơi khác trên máy tính của bạn -
.
Finished in 0.01 seconds (files took 0.11201 seconds to load)
1 example, 0 failures
Như bạn có thể thấy, sử dụng test doublecho phép bạn kiểm tra mã của mình ngay cả khi nó dựa trên một lớp không được xác định hoặc không có sẵn. Ngoài ra, điều này có nghĩa là khi có một bài kiểm tra không đạt, bạn có thể biết ngay rằng đó là do vấn đề trong lớp của bạn chứ không phải do lớp do người khác viết.