Python - Mocking and Stubbing

Python mocking and stubbing là những kỹ thuật quan trọng trong kiểm thử đơn vị giúp cô lập chức năng được kiểm thử bằng cách thay thế các đối tượng hoặc phương thức thực bằng các thay thế được kiểm soát. Trong chương này, chúng ta sẽ hiểu rõ về Mocking và Stubbing.

Python Mocking

Mocking là một kỹ thuật kiểm tra trong đó các đối tượng giả được tạo ra để mô phỏng hành vi của các đối tượng thực.

Điều này hữu ích khi kiểm tra một đoạn mã tương tác với các thành phần phức tạp, khó đoán hoặc chậm như cơ sở dữ liệu, dịch vụ web hoặc thiết bị phần cứng.

Mục đích chính của việc giả lập (mocking) là để tách biệt mã đang được kiểm tra và đảm bảo rằng hành vi của nó được đánh giá độc lập với các phụ thuộc của nó.

Key Characteristics of Mocking

Các đặc điểm chính của việc giả lập (mocking) trong Python bao gồm:

  • Behavior Simulation: Mock objects can be programmed to return specific values, raise exceptions or mimic the behavior of real objects under various conditions.
  • Interaction Verification: Mocks can record how they were used by allowing the tester to verify that specific methods were called with the expected arguments.
  • Test Isolation: By replacing real objects with mocks, tests can focus on the logic of the code under test without worrying about the complexities or availability of external dependencies.

Example of Python Mocking

Dưới đây là ví dụ về phương thức database.get_user , được giả lập để trả về một từ điển người dùng được định nghĩa trước. Bài kiểm tra sau đó có thể xác minh rằng phương thức đã được gọi với các tham số chính xác −

from unittest.mock import Mock

# Create a mock object
database = Mock()

# Simulate a method call
database.get_user.return_value = {"name": "Prasad", "age": 30}

# Use the mock object
user = database.get_user("prasad_id")
print(user)  

# Verify the interaction
database.get_user.assert_called_with("prasad_id") 

Output

{'name': 'Prasad', 'age': 30}

Python Stubbing

Stubbing là một kỹ thuật kiểm tra liên quan, trong đó một số methods hoặc functions được thay thế bằng "stubs" trả về các phản hồi cố định, đã được xác định trước.

Stubbing đơn giản hơn mocking vì nó thường không liên quan đến việc ghi lại hoặc xác minh các tương tác. Thay vào đó, stubbing tập trung vào việc cung cấp các đầu vào có kiểm soát cho mã đang được kiểm tra bằng cách đảm bảo các kết quả nhất quán và có thể lặp lại.

Key Characteristics of Stubbing

Các đặc điểm chính của Stubbing trong Python bao gồm:

  • Fixed Responses: Stubs return specific, predefined values or responses regardless of how they are called.
  • Simplified Dependencies: By replacing complex methods with stubs, tests can avoid the need to set up or manage intricate dependencies.
  • Focus on Inputs: Stubbing emphasizes providing known inputs to the code under test by allowing the tester to focus on the logic and output of the tested code.

Example of Python Stubbing

Dưới đây là ví dụ về hàm get_user_from_db , hàm này được định nghĩa để luôn trả về một từ điển người dùng đã được xác định trước. Bài kiểm tra không cần phải tương tác với cơ sở dữ liệu thực để đơn giản hóa việc thiết lập và đảm bảo kết quả nhất quán.

from unittest.mock import patch

# Define the function to be stubbed
def get_user_from_db(user_id):
   # Simulate a complex database operation
   pass

# Test the function with a stub
with patch('__main__.get_user_from_db', return_value={"name": "Prasad", "age": 25}):
   user = get_user_from_db("prasad_id")
   print(user)  

Output

{'name': 'Prasad', 'age': 25}

Python Mocking Vs. Stubbing

Việc so sánh các tính năng chính, mục đích và trường hợp sử dụng của Mocking và Stubbing giúp làm rõ khi nào nên sử dụng từng phương pháp. Bằng cách khám phá những sự khác biệt này, các nhà phát triển có thể tạo ra những bài kiểm tra hiệu quả và dễ bảo trì hơn, từ đó dẫn đến phần mềm có chất lượng cao hơn.

Bảng dưới đây cho thấy sự khác biệt chính giữa mocking và stubbing dựa trên các tiêu chí khác nhau −

Criteria Mocking Stubbing
Purpose Simulate the behavior of real objects Provide fixed, predetermined responses
Interaction Verification Can verify method calls and arguments Typically does not verify interactions
Complexity More complex; can simulate various behaviors Simpler; focuses on providing controlled inputs
Use Case Isolate and test code with complex dependencies Simplify tests by providing known responses
Recording Behavior Records how methods were called Does not record interactions
State Management Can maintain state across calls Usually stateless; returns fixed output
Framework Support Primarily uses unittest.mock with features like Mock and MagicMock Uses unittest.mock's patch for simple replacements
Flexibility Highly flexible; can simulate exceptions and side effects Limited flexibility; focused on return values