Con trăn xây dựng giả

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
    
    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ẽ 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ủ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 thay vì các tham chiếu "được nhập" mạnh hơn [có thể bị bắt bởi
  • 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[]
    
    
    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ác
  • Mã được viết phụ thuộc và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[]
    
    
    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ác

 

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[] 

9

Chú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ác

 


Thê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[]

8

Bằ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[]

0

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[]

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[]

5

Tuy 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[]

1

Tạ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[]

3

Bâ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[]

5

Giả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[]

1

Setter 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[]

2

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 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à setters

 

Chế 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[]

3

Vì 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

Chủ Đề