Khách hàng trong bài đăng này đề cập đến bất kỳ đối tượng nào tạo tác dụng phụ, chẳng hạn như đĩa hoặc mạng I/O. Hãy xem xét một lớp,
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4, nhận tin nhắn qua HTTP, tạo ra một số tác dụng phụ bằng cách tạo cơ sở hạ tầng đám mây và gửi tin nhắn qua HTTP để phản hồi
import http_client
class CloudCreator :
def __init__[self] :
self.network_client = http_client.HTTPClient[]
Chúng ta có thể kiểm tra
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 như sau
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
6 đã cho chúng tôi khả năng kiểm tra lớp
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 của chúng tôi mà không tạo ra bất kỳ tác dụng phụ nào trên mạng. Tuy nhiên, thiết kế này có một số sai sót. Nếu
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 sử dụng nhiều ứng dụng khách bên ngoài, chúng tôi cần xếp chồng nhiều cuộc gọi
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
6. Hơn nữa,
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 và các bài kiểm tra đơn vị của nó phụ thuộc rất nhiều vào
class CloudCreator :
def __init__[self, network_client: NetworkClient] :
self.network_client = network_client
1, điều này khiến việc thay đổi máy khách mạng trở nên khó khăn
Kỹ sư Fugue Josh Einhorn lưu ý một số nhược điểm khác của
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
6
- Sử dụng nó có nghĩa là có những phụ thuộc ngầm ở đâu đó trong lớp -- một nhà phát triển khác sẽ không bao giờ biết điều này. Trình xây dựng lập luận làm cho các phụ thuộc trở nên rõ ràng
- Khi tái cấu trúc các triển khai cơ bản, việc sử dụng
6 sẽ yêu cầu cập nhật nhiều bài kiểm tra đơn vị không liên quan và không phải lúc nào cũng rõ bài kiểm tra đơn vị nào sẽ yêu cầu thay đổi do việc sử dụng các chuỗi được mã hóa cứng củaimport unittest import http_client from unittest.mock import MagicMock, patch class TestCloudCreator [unittest.TestCase] : @patch['http_client.HTTPClient'] def setUp [self, mock_http_client_call] : self.mock_http_client = MagicMock[autospec=http_client.HTTPClient] # Recall that patch patches the _initialization_ call of classes mock_http_client_call.return_value = self.mock_http_client self.cloud_creator = CloudCreator[]
6 thay vì các tham chiếu "được nhập" mạnh hơn [có thể bị bắt bởiimport unittest import http_client from unittest.mock import MagicMock, patch class TestCloudCreator [unittest.TestCase] : @patch['http_client.HTTPClient'] def setUp [self, mock_http_client_call] : self.mock_http_client = MagicMock[autospec=http_client.HTTPClient] # Recall that patch patches the _initialization_ call of classes mock_http_client_call.return_value = self.mock_http_client self.cloud_creator = CloudCreator[]
- Sử dụng
6 là một mùi mã vì điều đó có nghĩa là lớp đang kiểm tra đã được ghép nối với một hoặc nhiều lớp cụ thể khácimport unittest import http_client from unittest.mock import MagicMock, patch class TestCloudCreator [unittest.TestCase] : @patch['http_client.HTTPClient'] def setUp [self, mock_http_client_call] : self.mock_http_client = MagicMock[autospec=http_client.HTTPClient] # Recall that patch patches the _initialization_ call of classes mock_http_client_call.return_value = self.mock_http_client self.cloud_creator = CloudCreator[]
- Mã được viết phụ thuộc vào
6 để kiểm tra đơn vị không thể chuyển sang các ngôn ngữ khác. Các ngôn ngữ được nhập tĩnh với trình biên dịch không cho phép vá khỉ [không có một số công việc nghiêm túc]. Một cấu trúc lại cấu trúc sẽ được yêu cầu để kiểm tra đơn vị chính xác một lớp như vậy bằng ngôn ngữ khácimport unittest import http_client from unittest.mock import MagicMock, patch class TestCloudCreator [unittest.TestCase] : @patch['http_client.HTTPClient'] def setUp [self, mock_http_client_call] : self.mock_http_client = MagicMock[autospec=http_client.HTTPClient] # Recall that patch patches the _initialization_ call of classes mock_http_client_call.return_value = self.mock_http_client self.cloud_creator = CloudCreator[]
Nói chung, nếu việc kiểm tra một lớp yêu cầu nhiều
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
6ing của các máy khách bên ngoài, thì đó là dấu hiệu cho thấy cần phải có một bộ tái cấu trúc. Các kỹ sư phần mềm có kinh nghiệm sẽ thấy rằng ví dụ này là cơ hội chính để đảo ngược phụ thuộcĐảo ngược phụ thuộc và tiêm
Đảo ngược phụ thuộc, và cụ thể là tiêm phụ thuộc trong trường hợp này, là những chủ đề quen thuộc trong giới công nghệ phần mềm; . Điều này cho phép mã hoạt động trong nhiều ngữ cảnh, tùy thuộc vào ứng dụng khách nào được cung cấp.
Trong ví dụ của chúng tôi, chức năng cốt lõi của
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 là tạo cơ sở hạ tầng đám mây không phụ thuộc vào bất kỳ phương tiện cụ thể nào để gửi và nhận tin nhắn. Do đó, thật hợp lý khi viết lớp theo cách mà I/O của mạng được xử lý bởi một máy khách được đưa vào trong thời gian chạy, thay vì được mã hóa cứng [mã này sử dụng cú pháp gợi ý kiểu của Python]
class CloudCreator :
def __init__[self, network_client: NetworkClient] :
self.network_client = network_client
Việc đóng gói này cho phép lớp được sử dụng với ứng dụng khách HTTP, ứng dụng khách TCP/IP, ứng dụng khách ZMQ hoặc ứng dụng khách SQS/SNS, miễn là I/O của mạng tuân theo giao diện được chỉ định trước được xác định trong
class CloudCreator :
def __init__[self, network_client: NetworkClient] :
self.network_client = network_client
9, chẳng hạn . Đây là một sự đơn giản hóa tuyệt vời của quy trình và những người quan sát sắc sảo sẽ lưu ý rằng đặc điểm kỹ thuật của giao diện máy khách trở nên hết sức quan trọng, nhưng đó là một bài đăng trên blog khác
Một trong những ưu điểm chính của phép nội xạ phụ thuộc là nó cho phép nhà phát triển dễ dàng chuyển các đối tượng giả khi thử nghiệm đơn vị. Bây giờ chúng ta có thể thiết lập các bài kiểm tra của mình như thế này
import http_client
class CloudCreator :
def __init__[self] :
self.network_client = http_client.HTTPClient[]
9Chúng tôi tạo một ứng dụng khách mạng giả để thử nghiệm đơn vị, sử dụng đối số
import http_client
class CloudCreator :
def __init__[self] :
self.network_client = http_client.HTTPClient[]
92 của
import http_client
class CloudCreator :
def __init__[self] :
self.network_client = http_client.HTTPClient[]
93 để tạo một đối tượng giả tuân thủ giao diện
class CloudCreator :
def __init__[self, network_client: NetworkClient] :
self.network_client = network_client
9
Trong ví dụ đơn giản này,
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
6 cho phép chúng tôi viết lại một thiết kế không linh hoạt bằng cách tạo một bài kiểm tra đơn vị thậm chí còn không linh hoạt hơn. Như tôi đã lưu ý trước đó, nếu bạn đang vá nhiều hơn một vài cuộc gọi, đó là dấu hiệu cho thấy bạn nên cấu trúc lại. Lưu ý rằng
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
6 vẫn hữu ích, ví dụ, để vá các lệnh gọi tới
import http_client
class CloudCreator :
def __init__[self] :
self.network_client = http_client.HTTPClient[]
97 hoặc các lệnh gọi thư viện không có tác dụng phụ khácThêm phụ thuộc tiêm
Dependency injection rất hữu ích, nhưng chúng ta nên làm gì khi class của chúng ta cần một số lượng lớn client?
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
8Bằng cách thêm các giá trị mặc định, có thể khởi tạo ứng dụng khách một cách có chọn lọc, điều này giúp việc kiểm tra đơn vị dễ dàng hơn [sẽ nói thêm về điều này sau]. Tuy nhiên, hình thức này vẫn còn khó sử dụng, đặc biệt là khi thực hiện kiểm thử tích hợp. Xem xét điều gì sẽ xảy ra nếu chúng tôi thực hiện thay đổi đối với trình xử lý thư của mình và sau đó, muốn kiểm tra xem trình xử lý đó có giao tiếp chính xác với máy chủ không. Khởi tạo một
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 mất rất nhiều công việc tẻ nhạt để tạo và khởi tạo các đối tượng máy khách. Một trong những điểm mạnh của Python là trình thông dịch tương tác của nó, cho phép quá trình phát triển lặp đi lặp lại và duy trì khả năng sử dụng REPL dễ dàng giúp cuộc sống của các nhà phát triển dễ dàng hơn. Việc yêu cầu các nhà phát triển tạo và khởi tạo hàng chục đối tượng máy khách trước khi họ có thể kiểm tra một thay đổi nhỏ đối với lớp lõi tạo ra sự thất vọng
Một giải pháp là đóng gói việc tạo ứng dụng khách trong một đối tượng riêng biệt. Chúng tôi thậm chí có thể mã hóa thông tin về thứ tự hoạt động và các phụ thuộc trong hàm tạo
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
0Lưu ý rằng
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 vẫn được khởi tạo với các tham chiếu rõ ràng đến các dịch vụ mà nó yêu cầu. Điều này giúp các nhà phát triển trong tương lai dễ dàng hiểu được dịch vụ mà
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 yêu cầu. Có thể đưa ra đối số cho một thiết kế trong đó hàm tạo của
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 chỉ mong đợi một đối tượng
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
82
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
5Tuy nhiên, điều này ràng buộc
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 với việc triển khai cụ thể của
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
82, với chính xác các dịch vụ mà
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 yêu cầu. Nếu
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
82 được khái quát hóa để tạo các dịch vụ cho nhiều lớp, người gọi phải giả định rằng mọi dịch vụ đơn lẻ đều được yêu cầu bởi bất kỳ lớp nào sử dụng lớp
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
87 được tổng quát hóa
Thật không may, việc triển khai ngây thơ này làm mất tính linh hoạt của phép tiêm phụ thuộc thô. Một bước tiến, một bước lùi. Điều này dễ dàng khắc phục
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
1Tại thời điểm này, tất cả những gì chúng tôi đã làm là di chuyển sự phức tạp xung quanh. Nhà phát triển vẫn chịu trách nhiệm khởi tạo tất cả các máy khách. Chúng tôi chưa cung cấp bất kỳ công cụ nào để giúp cuộc sống của họ dễ dàng hơn. Chúng ta có thể làm điều đó bằng cách xây dựng các thủ tục khởi tạo phức tạp thành
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
82
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
3Bây giờ chúng tôi đã ẩn việc tạo ứng dụng khách trong các phương thức khởi tạo này. Đây có vẻ là một giải pháp tốt, nhưng nếu chúng ta xem xét kỹ hơn, thì có một nhược điểm. Khi khởi tạo
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
82, chúng tôi tạo mọi ứng dụng khách, ngay cả khi chúng tôi biết rằng mình sẽ không sử dụng nó. Chúng tôi phải làm gì nếu một trong các dịch vụ khách hàng của chúng tôi hoạt động sai và hết thời gian, nhưng chúng tôi vẫn muốn kiểm tra chức năng khác?
Chúng ta có thể sử dụng các phương thức getter để thay đổi thứ tự của bất biến khởi tạo
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
5Giải pháp này cung cấp cho chúng tôi tải chậm, vì vậy các máy khách chỉ được khởi tạo khi cần thiết trong khi vẫn duy trì khả năng hoán đổi các máy khách khi cần. Tuy nhiên, các phương thức getter không phải là Pythonic lắm. Có tính năng ngôn ngữ nào mà chúng tôi có thể khai thác để tìm ra cách Pythonic hơn không?
@tài sản
Tính năng chúng tôi đang tìm kiếm là
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
00
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
0Điều này trông giống như giải pháp trước đây của chúng tôi với các phương thức getter, nhưng chúng tôi đã loại bỏ
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
01 và chúng tôi đã thêm trình trang trí
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
00.
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
00 biến phương thức getter thành thuộc tính. Một thuộc tính có thể được truy cập trực tiếp, chẳng hạn như
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
04, không cần dấu ngoặc đơn. Hơn nữa, việc sử dụng
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
00 cho chúng ta tùy chọn để thêm một setter trong tương lai, bằng cách trang trí hàm setter cho một thuộc tính với
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
06 chẳng hạn
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
1Setter sẽ được gọi rõ ràng khi chúng ta gán giá trị cho
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
07
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
2Việc sử dụng
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
00 duy trì tiêu chuẩn Python để truy cập trực tiếp các thuộc tính đối tượng, đồng thời mang lại cho chúng tôi sự linh hoạt trong việc gói quyền truy cập thuộc tính trong getters và settersChế giễu với tiêm phụ thuộc
Một trong những ưu điểm của đảo ngược phụ thuộc là nó làm cho việc kiểm tra đơn vị trở nên đơn giản hơn nhiều. Nhớ lại rằng các đối số khởi tạo của
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
4 có các giá trị mặc định, cho phép chúng tôi mô phỏng có chọn lọc các đối tượng dịch vụ khách hàng cho các thử nghiệm cụ thể
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
3Vì các dịch vụ máy khách khác chưa được khởi tạo nên rất dễ biết liệu đường dẫn mã mạng có chạm vào các đối tượng bên ngoài phạm vi của nó hay không, đây thường là dấu hiệu cho thấy có điều gì đó không ổn. Tất nhiên, các bài kiểm tra đơn vị toàn diện sẽ yêu cầu mô phỏng cho mọi dịch vụ, nhưng chúng rất dễ thêm vào
Bằng cách sử dụng đảo ngược phụ thuộc, chúng tôi đã loại bỏ nhu cầu về
import unittest
import http_client from unittest.mock
import MagicMock, patch
class TestCloudCreator [unittest.TestCase] :
@patch['http_client.HTTPClient']
def setUp [self, mock_http_client_call] :
self.mock_http_client = MagicMock[autospec=http_client.HTTPClient]
# Recall that patch patches the _initialization_ call of classes
mock_http_client_call.return_value = self.mock_http_client
self.cloud_creator = CloudCreator[]
6ing trong các bài kiểm tra đơn vị của mình, đồng thời cung cấp cho các nhà phát triển một công cụ mạnh mẽ, tiết kiệm thời gian để kiểm tra tích hợp