Sự khác biệt giữa giả mạo, chế giễu và sơ khai là gì?


705

Tôi biết làm thế nào tôi sử dụng các thuật ngữ này, nhưng tôi tự hỏi liệu có các định nghĩa được chấp nhận để giả mạo , chế giễukhai thác cho các bài kiểm tra đơn vị không? Làm thế nào để bạn xác định những điều này cho các bài kiểm tra của bạn? Mô tả các tình huống mà bạn có thể sử dụng từng tình huống.

Đây là cách tôi sử dụng chúng:

Fake : một lớp thực hiện một giao diện nhưng chứa dữ liệu cố định và không có logic. Chỉ cần trả về dữ liệu "tốt" hoặc "xấu" tùy theo việc triển khai.

Mock : một lớp thực hiện một giao diện và cho phép khả năng tự động đặt các giá trị thành trả về / ngoại lệ để ném từ các phương thức cụ thể và cung cấp khả năng kiểm tra xem các phương thức cụ thể đã được gọi / chưa được gọi chưa.

Sơ khai : Giống như một lớp giả, ngoại trừ việc nó không cung cấp khả năng xác minh rằng các phương thức đã được gọi / không được gọi.

Giả và cuống có thể được tạo bằng tay hoặc được tạo bởi khung mô phỏng. Các lớp giả được tạo bằng tay. Tôi sử dụng giả chủ yếu để xác minh các tương tác giữa lớp của tôi và các lớp phụ thuộc. Tôi sử dụng sơ khai một khi tôi đã xác minh các tương tác và đang thử nghiệm các đường dẫn thay thế thông qua mã của tôi. Tôi sử dụng các lớp giả mạo chủ yếu để trừu tượng hóa các phụ thuộc dữ liệu hoặc khi các mock / stub quá tẻ nhạt để thiết lập mỗi lần.


6
Vâng, về cơ bản, bạn đã nói tất cả trong "câu hỏi" của mình :) Tôi nghĩ đó là những định nghĩa được chấp nhận khá tốt về các điều khoản đó
Eran Galperin

2
Định nghĩa Wikipedia về Fake khác với điều này, khẳng định rằng Fake "được sử dụng như một cách thực hiện đơn giản hơn, ví dụ: sử dụng cơ sở dữ liệu trong bộ nhớ trong các bài kiểm tra thay vì truy cập cơ sở dữ liệu thực)" Xem en.wikipedia.org/wiki/Test_double
zumalifeguard

2
Tôi đã học được rất nhiều từ tài nguyên sau đây, với lời giải thích tuyệt vời của Robert C. Martin (Chú Bob): The Mocker nhỏ trên Blog Clean Code . Nó giải thích sự khác biệt giữa và sự tinh tế của người giả, nhân đôi kiểm tra, sơ khai, gián điệp, giả (thật) giả và giả. Nó cũng đề cập đến Martin Fowler và nó giải thích một chút về lịch sử kiểm thử phần mềm.
Erik

tests.googleblog.com/2013/07/ trên (tóm tắt một trang ngắn).
ShreevatsaR

Dưới đây là ý kiến ​​của tôi để giải thích rằng: Kiểm tra nhân đôi: Fakes, Stub và Mocks (bài đăng trên blog với các ví dụ)
michal-lipki

Câu trả lời:


548

Bạn có thể nhận được một số thông tin:

Từ Martin Fowler về Mock và Stub

Các đối tượng giả thực sự có triển khai hoạt động, nhưng thường sử dụng một số phím tắt khiến chúng không phù hợp để sản xuất

Sơ khai cung cấp câu trả lời đóng hộp cho các cuộc gọi được thực hiện trong quá trình thử nghiệm, thường không phản hồi hoàn toàn cho bất kỳ điều gì bên ngoài những gì được lập trình trong thử nghiệm. Sơ khai cũng có thể ghi lại thông tin về các cuộc gọi, chẳng hạn như một cổng thông tin email còn nhớ các tin nhắn mà nó 'đã gửi' hoặc có thể chỉ có bao nhiêu tin nhắn mà nó 'đã gửi'.

Giả là những gì chúng ta đang nói ở đây: các đối tượng được lập trình sẵn với những kỳ vọng hình thành nên một đặc điểm kỹ thuật của các cuộc gọi mà chúng dự kiến ​​sẽ nhận được.

Từ xunitpotype :

Giả mạo : Chúng tôi có được hoặc xây dựng một triển khai rất nhẹ chức năng tương tự như được cung cấp bởi một thành phần mà SUT phụ thuộc và hướng dẫn SUT sử dụng nó thay vì thực tế.

Sơ khai : Việc triển khai này được định cấu hình để đáp ứng các cuộc gọi từ SUT với các giá trị (hoặc ngoại lệ) sẽ thực thi Mã chưa được kiểm tra (xem Lỗi sản xuất trên trang X) trong SUT. Một dấu hiệu chính để sử dụng Sơ đồ kiểm tra là có Mã chưa được kiểm tra do không thể kiểm soát các đầu vào gián tiếp của SUT

Mock Object thực hiện giao diện giống như một đối tượng mà SUT (System Under Test) phụ thuộc vào. Chúng ta có thể sử dụng Đối tượng giả làm điểm quan sát khi chúng ta cần thực hiện Xác minh hành vi để tránh yêu cầu chưa được kiểm tra (xem Lỗi sản xuất trên trang X) do không thể quan sát tác dụng phụ của các phương thức gọi trên SUT.

Cá nhân

Tôi cố gắng đơn giản hóa bằng cách sử dụng: Mock và Stub. Tôi sử dụng Mock khi nó là một đối tượng trả về một giá trị được đặt thành lớp được kiểm tra. Tôi sử dụng Stub để bắt chước một lớp Interface hoặc Trừu tượng để kiểm tra. Trên thực tế, việc bạn gọi nó là gì không thực sự quan trọng, chúng đều là các lớp không được sử dụng trong sản xuất và được sử dụng làm lớp tiện ích để thử nghiệm.


9
Dường như với tôi các định nghĩa cho Stub và Fake được đảo ngược trong trích dẫn xUnitPotype so với trích dẫn của Martin Fowler. Ngoài ra, các định nghĩa về Stub và Fake của Martin Fowler bị đảo ngược so với các định nghĩa trong câu hỏi ban đầu của tvanfosson. Trong thực tế, có bất kỳ định nghĩa được chấp nhận chung về hai thuật ngữ đó hay nó chỉ phụ thuộc vào việc bạn đang nói chuyện với ai?
Simon Tewsi

3
+1 cho "Tôi cố gắng đơn giản hóa bằng cách sử dụng: Mock và Stub". Đó là một ý tưởng tuyệt vời!
Brad Cupit

4
Không thể thấy chỉ sử dụng Mock và Stub là một ý tưởng tuyệt vời. Mỗi thử nghiệm đôi có mục đích của nó và, do đó, sử dụng của nó.
Hector Ordonez

1
Tôi không thể thấy sự khác biệt giữa Fake và Mock trong định nghĩa của MF.
IdontCare AboutReputingPoints

2
@MusuNaji: Theo định nghĩa của MF, không có "kỳ vọng" nào liên quan đến cuộc trò chuyện về Fake, ngoài việc nó có triển khai cho giao diện của nó. Mặt khác, Mock sẽ bị thử thách (phương pháp này có được gọi là?).
dbalakirev

205

Sơ khai - một đối tượng cung cấp câu trả lời được xác định trước cho các cuộc gọi phương thức.

Mock - một đối tượng mà bạn đặt kỳ vọng.

Fake - một đối tượng có khả năng hạn chế (cho mục đích thử nghiệm), ví dụ: dịch vụ web giả mạo.

Test Double là thuật ngữ chung cho cuống, giả và giả. Nhưng không chính thức, bạn sẽ thường nghe mọi người chỉ đơn giản gọi họ là giả.


4
Bất cứ ai có thể giải thích và định nghĩa cho tôi "câu trả lời đóng hộp" trong bối cảnh này là gì?
MasterMastic

14
Một giá trị rõ ràng, thay vì một giá trị được tính toán.
Mike

Cuối cùng! Một số định nghĩa tôi có thể hiểu! Sau đó, dựa trên các định nghĩa này, googletest (gtest) / googlemock (gmock) cho phép các đối tượng bị giả cũng là sơ khai, vì bạn có thể tạo EXPECT_CALL()s trên một phương thức giả, buộc các đầu ra nhất định dựa trên loại đầu vào nhất định, bằng cách sử dụng loại .WillOnce(Invoke(my_func_or_lambda_func))(hoặc với .WillRepeatedly()) cú pháp gắn liền với một EXPECT_CALL(). Một số ví dụ về việc sử dụng Invoke()có thể được nhìn thấy trong một bối cảnh khác ở cuối câu trả lời dài của tôi ở đây: stackoverflow.com/a/60905880/4561887 .
Gabriel Staples

Tài liệu Gmock trên Invoke()có tại đây: github.com/google/googletest/blob/master/googlemock/docs/ . Dù sao, kết luận là: Google mock (gmock) cho phép một người dễ dàng tạo cả giả cuống , mặc dù hầu hết các giả đều không phải là sơ khai.
Gabriel Staples

Mocks là một superset của Stub, chúng vẫn có thể trả về các câu trả lời được xác định trước nhưng cũng cho phép nhà phát triển đặt kỳ vọng. IMO một số thư viện ngoài kia làm mờ các dòng của tất cả các hình nộm thử nghiệm.
Lu-ca

94

Tôi ngạc nhiên rằng câu hỏi này đã có từ rất lâu và chưa ai đưa ra câu trả lời dựa trên "Nghệ thuật kiểm tra đơn vị" của Roy Osherove .

Trong "3.1 Giới thiệu sơ khai" định nghĩa sơ khai là:

Sơ khai là một thay thế có thể kiểm soát cho một phụ thuộc hiện có (hoặc cộng tác viên) trong hệ thống. Bằng cách sử dụng sơ khai, bạn có thể kiểm tra mã của mình mà không phải xử lý trực tiếp phụ thuộc.

Và xác định sự khác biệt giữa sơ khai và giả là:

Điều chính cần nhớ về giả so với sơ khai là các giả giống như cuống, nhưng bạn khẳng định chống lại đối tượng giả, trong khi bạn không khẳng định chống lại sơ khai.

Fake chỉ là tên được sử dụng cho cả sơ khai và giả. Ví dụ: khi bạn không quan tâm đến sự khác biệt giữa cuống và giả.

Cách Osherove phân biệt giữa cuống và giả, có nghĩa là bất kỳ lớp nào được sử dụng làm giả để thử nghiệm đều có thể là sơ khai hoặc giả. Việc kiểm tra cụ thể hoàn toàn phụ thuộc vào cách bạn viết séc trong bài kiểm tra của mình.

  • Khi kiểm tra của bạn kiểm tra các giá trị trong lớp được kiểm tra, hoặc thực sự ở bất cứ nơi nào ngoại trừ giả, giả mạo đã được sử dụng như một sơ khai. Nó chỉ cung cấp các giá trị cho lớp đang thử nghiệm để sử dụng, trực tiếp thông qua các giá trị được trả về bởi các cuộc gọi trên nó hoặc gián tiếp thông qua việc gây ra tác dụng phụ (ở một số trạng thái) do kết quả của các cuộc gọi trên nó.
  • Khi kiểm tra của bạn kiểm tra giá trị của giả, nó đã được sử dụng như một bản giả.

Ví dụ về một bài kiểm tra trong đó lớp FakeX được sử dụng làm sơ khai:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, cut.SomeProperty);

Các fakeví dụ được sử dụng như một cuống vìAssert không sử dụng fakeở tất cả.

Ví dụ về một bài kiểm tra trong đó lớp kiểm tra X được sử dụng làm giả:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, fake.SomeProperty);

Trong trường hợp này Assert kiểm tra một giá trị trên fake, làm cho giả đó thành một giả.

Bây giờ, tất nhiên những ví dụ này rất có ý nghĩa, nhưng tôi thấy công đức lớn trong sự khác biệt này. Nó làm cho bạn biết về cách bạn đang kiểm tra công cụ của mình và nơi phụ thuộc của bài kiểm tra của bạn.

Tôi đồng ý với Osherove rằng

từ quan điểm duy trì thuần túy, trong các thử nghiệm của tôi sử dụng giả tạo tạo ra nhiều rắc rối hơn là không sử dụng chúng. Đó là kinh nghiệm của tôi, nhưng tôi luôn học được điều gì đó mới mẻ.

Khẳng định chống lại sự giả mạo là điều bạn thực sự muốn tránh vì nó làm cho các bài kiểm tra của bạn phụ thuộc rất nhiều vào việc thực hiện một lớp không phải là bài kiểm tra. Điều đó có nghĩa là các bài kiểm tra cho lớp ActualClassUnderTestcó thể bắt đầu phá vỡ vì việc thực hiện ClassUsedAsMockđã thay đổi. Và điều đó gửi lên một mùi hôi cho tôi. Các xét nghiệm choActualClassUnderTest tốt nhất chỉ nên phá vỡ khi ActualClassUnderTestđược thay đổi.

Tôi nhận ra rằng viết khẳng định chống lại giả là một cách phổ biến, đặc biệt khi bạn là một loại thuê bao TDD nhạo báng. Tôi đoán tôi chắc chắn với Martin Fowler trong trại cổ điển (Xem "Mocks not Stub" của Martin Fowler ) và giống như Osherove tránh thử nghiệm tương tác (chỉ có thể được thực hiện bằng cách khẳng định chống lại kẻ giả mạo) càng nhiều càng tốt.

Để đọc vui về lý do tại sao bạn nên tránh các giả định như được định nghĩa ở đây, google cho "fowler mockist classicist". Bạn sẽ tìm thấy rất nhiều ý kiến.


30

Như được đề cập bởi câu trả lời được bình chọn hàng đầu, Martin Fowler thảo luận về những điểm khác biệt này trong Mocks Ar't Stub , và đặc biệt là phân nhóm Sự khác biệt giữa Mocks và Stub , vì vậy hãy chắc chắn đọc bài viết đó.

Thay vì tập trung vào việc những thứ này khác nhau như thế nào , tôi nghĩ sẽ tập trung hơn vào việc tại sao đây là những khái niệm riêng biệt. Mỗi tồn tại cho một mục đích khác nhau.

Hàng giả

Một giả là một thực hiện mà cư xử "một cách tự nhiên", nhưng không phải là "thật". Đây là những khái niệm mờ nhạt và vì vậy những người khác nhau có những cách hiểu khác nhau về những gì làm cho mọi thứ trở thành giả.

Một ví dụ về giả là cơ sở dữ liệu trong bộ nhớ (ví dụ: sử dụng sqlite với :memory: cửa hàng). Bạn sẽ không bao giờ sử dụng điều này cho sản xuất (vì dữ liệu không được duy trì), nhưng nó hoàn toàn đầy đủ như một cơ sở dữ liệu để sử dụng trong môi trường thử nghiệm. Nó cũng nhẹ hơn nhiều so với cơ sở dữ liệu "thực".

Một ví dụ khác, có lẽ bạn sử dụng một số loại kho đối tượng (ví dụ Amazon S3) trong sản xuất, nhưng trong thử nghiệm, bạn có thể chỉ cần lưu đối tượng vào các tệp trên đĩa; thì việc thực hiện "lưu vào đĩa" của bạn sẽ là giả mạo. (Hoặc thậm chí bạn có thể giả mạo thao tác "lưu vào đĩa" bằng cách sử dụng hệ thống tệp trong bộ nhớ thay thế.)

Như một ví dụ thứ ba, hãy tưởng tượng một đối tượng cung cấp API bộ đệm; một đối tượng thực hiện giao diện chính xác nhưng chỉ đơn giản là không thực hiện bộ nhớ đệm mà luôn trả về lỗi bộ nhớ cache sẽ là một loại giả mạo.

Mục đích của việc giả mạo không phải là để ảnh hưởng đến hành vi của hệ thống được thử nghiệm , mà là để đơn giản hóa việc thực hiện thử nghiệm (bằng cách loại bỏ các phụ thuộc không cần thiết hoặc nặng).

Sơ khai

Một sơ khai là một thực hiện mà ứng xử "không tự nhiên". Nó được cấu hình sẵn (thường là do thiết lập thử nghiệm) để đáp ứng với các đầu vào cụ thể với các đầu ra cụ thể.

Mục đích của sơ khai là đưa hệ thống của bạn vào thử nghiệm ở trạng thái cụ thể. Ví dụ: nếu bạn đang viết thử nghiệm cho một số mã tương tác với API REST, bạn có thể loại bỏ API REST bằng API luôn trả về phản hồi đóng hộp hoặc phản hồi yêu cầu API có lỗi cụ thể. Bằng cách này, bạn có thể viết các bài kiểm tra để khẳng định về cách hệ thống phản ứng với các trạng thái này; ví dụ: kiểm tra phản hồi mà người dùng của bạn nhận được nếu API trả về lỗi 404.

Một sơ khai thường được thực hiện để chỉ đáp ứng với các tương tác chính xác mà bạn đã nói với nó để đáp ứng. Nhưng tính năng chính làm cho một cái gì đó còn sơ khai là mục đích của nó : một sơ khai là tất cả về việc thiết lập trường hợp thử nghiệm của bạn.

Giả

Một bản giả tương tự như một sơ khai, nhưng có thêm xác minh . Mục đích của bản giả là đưa ra các xác nhận về cách hệ thống của bạn được kiểm tra tương tác với phụ thuộc .

Ví dụ: nếu bạn đang viết bài kiểm tra cho một hệ thống tải tệp lên trang web, bạn có thể tạo một bản giả chấp nhận tệp và bạn có thể sử dụng để xác nhận rằng tệp đã tải lên là chính xác. Hoặc, ở quy mô nhỏ hơn, người ta thường sử dụng giả của một đối tượng để xác minh rằng hệ thống được thử nghiệm gọi các phương thức cụ thể của đối tượng bị giả.

Mocks gắn liền với thử nghiệm tương tác , đây là một phương pháp thử nghiệm cụ thể. Những người thích kiểm tra trạng thái hệ thống hơn là tương tác hệ thống sẽ sử dụng giả một cách tiết kiệm nếu có.

Kiểm tra đôi

Hàng giả, cuống và giả đều thuộc về loại thử nghiệm nhân đôi . Kiểm tra kép là bất kỳ đối tượng hoặc hệ thống nào bạn sử dụng trong kiểm tra thay vì một thứ khác. Hầu hết các kiểm thử phần mềm tự động liên quan đến việc sử dụng các phép thử nhân đôi bằng cách này hay cách khác. Một số loại nhân đôi kiểm tra khác bao gồm các giá trị giả , gián điệp , và I / O blackholes .


11

Để minh họa việc sử dụng sơ khai và giả, tôi cũng muốn đưa vào một ví dụ dựa trên " Nghệ thuật kiểm tra đơn vị của Roy Osherove .

Hãy tưởng tượng, chúng ta có một ứng dụng LogAnalyzer có chức năng duy nhất là in nhật ký. Nó không chỉ cần nói chuyện với một dịch vụ web, mà nếu dịch vụ web đó gặp lỗi, LogAnalyzer phải ghi lại lỗi cho một phụ thuộc bên ngoài khác, gửi nó qua email cho quản trị viên dịch vụ web.

Đây là logic chúng tôi muốn kiểm tra bên trong LogAnalyzer:

if(fileName.Length<8)
{
 try
  {
    service.LogError("Filename too short:" + fileName);
  }
 catch (Exception e)
  {
    email.SendEmail("a","subject",e.Message);
  }
}

Làm thế nào để bạn kiểm tra rằng LogAnalyzer gọi dịch vụ email một cách chính xác khi dịch vụ web ném ngoại lệ? Dưới đây là những câu hỏi chúng tôi phải đối mặt:

  • Làm thế nào chúng ta có thể thay thế dịch vụ web?

  • Làm cách nào chúng tôi có thể mô phỏng một ngoại lệ từ dịch vụ web để chúng tôi có thể kiểm tra cuộc gọi đến dịch vụ email?

  • Làm thế nào chúng ta sẽ biết rằng dịch vụ email đã được gọi chính xác hay hoàn toàn?

Chúng tôi có thể giải quyết hai câu hỏi đầu tiên bằng cách sử dụng sơ khai cho dịch vụ web . Để giải quyết vấn đề thứ ba, chúng ta có thể sử dụng một đối tượng giả cho dịch vụ email .

Giả là một thuật ngữ chung có thể được sử dụng để mô tả sơ khai hoặc giả. Trong thử nghiệm của chúng tôi, chúng tôi sẽ có hai giả mạo. Một sẽ là giả lập dịch vụ email, chúng tôi sẽ sử dụng để xác minh rằng các tham số chính xác đã được gửi đến dịch vụ email. Cái còn lại sẽ còn sơ khai mà chúng ta sẽ sử dụng để mô phỏng một ngoại lệ được ném ra từ dịch vụ web. Đó là một sơ khai vì chúng tôi sẽ không sử dụng dịch vụ web giả để xác minh kết quả kiểm tra, chỉ để đảm bảo kiểm tra chạy chính xác. Dịch vụ email là một bản giả vì chúng tôi sẽ khẳng định rằng nó được gọi chính xác.

[TestFixture]
public class LogAnalyzer2Tests
{
[Test]
 public void Analyze_WebServiceThrows_SendsEmail()
 {
   StubService stubService = new StubService();
   stubService.ToThrow= new Exception("fake exception");
   MockEmailService mockEmail = new MockEmailService();

   LogAnalyzer2 log = new LogAnalyzer2();
   log.Service = stubService
   log.Email=mockEmail;
   string tooShortFileName="abc.ext";
   log.Analyze(tooShortFileName);

   Assert.AreEqual("a",mockEmail.To); //MOCKING USED
   Assert.AreEqual("fake exception",mockEmail.Body); //MOCKING USED
   Assert.AreEqual("subject",mockEmail.Subject);
 }
}

9

thứ mà bạn khẳng định trên nó, được gọi là một đối tượng giả và mọi thứ khác chỉ giúp chạy thử, là còn sơ khai .


1
trong khi các câu trả lời khác có chi tiết tuyệt vời và thực sự tốt Điều này làm cho nó rất rõ ràng và dễ dàng để tạo ra sự khác biệt, thật khó để không nâng cao. gj
Mario Garcia

6

Đó là một vấn đề làm cho các bài kiểm tra biểu cảm. Tôi đặt kỳ vọng vào Mock nếu tôi muốn thử nghiệm mô tả mối quan hệ giữa hai đối tượng. Tôi vẫn trả lại các giá trị nếu tôi thiết lập một đối tượng hỗ trợ để đưa tôi đến hành vi thú vị trong thử nghiệm.


6

Nếu bạn đã quen thuộc với Arrange-Act-Assert, thì một cách giải thích sự khác biệt giữa sơ khai và giả có thể hữu ích cho bạn, đó là các cuống thuộc về phần sắp xếp, vì chúng là để sắp xếp trạng thái đầu vào và giả là phần khẳng định như họ là để khẳng định kết quả chống lại.

Người giả không làm gì cả. Chúng chỉ để điền vào danh sách tham số, do đó bạn không nhận được lỗi không xác định hoặc null. Chúng cũng tồn tại để đáp ứng trình kiểm tra loại bằng các ngôn ngữ được nhập chính xác, để bạn có thể được phép biên dịch và chạy.


3

Stub, Fakes và Mocks có ý nghĩa khác nhau trên các nguồn khác nhau. Tôi đề nghị bạn giới thiệu các điều khoản nội bộ của nhóm của bạn và đồng ý với ý nghĩa của chúng.

Tôi nghĩ điều quan trọng là phải phân biệt giữa hai cách tiếp cận: - xác thực hành vi (ngụ ý thay thế hành vi) - xác nhận trạng thái kết thúc (ngụ ý mô phỏng hành vi)

Xem xét gửi email trong trường hợp có lỗi. Khi làm xác nhận hành vi - bạn kiểm tra xem phương pháp Sendcủa IEmailSenderđược thực hiện một lần. Và bạn cần mô phỏng kết quả trả về của phương thức này, trả về Id của tin nhắn đã gửi. Vì vậy, bạn nói: "Tôi hy vọng rằng nó Sendsẽ được gọi. Và tôi sẽ chỉ trả lại Id giả (hoặc ngẫu nhiên) cho bất kỳ cuộc gọi nào" . Đây là xác nhận hành vi: emailSender.Expect(es=>es.Send(anyThing)).Return((subject,body) => "dummyId")

Khi thực hiện xác nhận trạng thái, bạn sẽ cần phải TestEmailSenderthực hiện điều đó IEmailSender. Và Sendphương thức thực hiện - bằng cách lưu dữ liệu đầu vào vào một số cấu trúc dữ liệu sẽ được sử dụng để xác minh trạng thái trong tương lai như mảng của một số đối tượng SentEmailsvà sau đó nó kiểm tra bạn sẽ kiểm tra xem SentEmailscó chứa email dự kiến ​​hay không. Đây là xác nhận trạng thái: Assert.AreEqual(1, emailSender.SentEmails.Count)

Từ bài đọc của tôi, tôi hiểu rằng xác nhận hành vi thường được gọi là Mocks . Và xác nhận nhà nước thường được gọi là Sơ khai hoặc Fakes .


Thực sự rất chi tiết và sắc nét sắc nét.
shyam sundar singh tomar

2

còn sơ khaigiả là các đối tượng ở chỗ chúng có thể thay đổi phản ứng của chúng dựa trên các tham số đầu vào. sự khác biệt chính giữa chúng là Fake gần với việc triển khai trong thế giới thực hơn là sơ khai. Sơ khai chứa các câu trả lời cơ bản được mã hóa cứng cho một yêu cầu dự kiến. Hãy xem một ví dụ:

public class MyUnitTest {

 @Test
 public void testConcatenate() {
  StubDependency stubDependency = new StubDependency();
  int result = stubDependency.toNumber("one", "two");
  assertEquals("onetwo", result);
 }
}

public class StubDependency() {
 public int toNumber(string param) {
  if (param == “one”) {
   return 1;
  }
  if (param == “two”) {
   return 2;
  }
 }
}

Một mô hình là một bước tiến từ hàng giả và cuống. Mocks cung cấp chức năng tương tự như sơ khai nhưng phức tạp hơn. Họ có thể có các quy tắc được xác định cho họ ra lệnh theo phương thức thứ tự nào trên API của họ phải được gọi. Hầu hết các giả đều có thể theo dõi số lần một phương thức được gọi và có thể phản ứng dựa trên thông tin đó. Mocks thường biết bối cảnh của mỗi cuộc gọi và có thể phản ứng khác nhau trong các tình huống khác nhau. Bởi vì điều này, giả lập đòi hỏi một số kiến ​​thức về lớp học mà họ đang chế giễu. một sơ khai thường không thể theo dõi số lần một phương thức được gọi hoặc theo thứ tự một chuỗi các phương thức được gọi. Một bản giả trông giống như:

public class MockADependency {

 private int ShouldCallTwice;
 private boolean ShouldCallAtEnd;
 private boolean ShouldCallFirst;

 public int StringToInteger(String s) {
  if (s == "abc") {
   return 1;
  }
  if (s == "xyz") {
   return 2;
  }
  return 0;
 }

 public void ShouldCallFirst() {
  if ((ShouldCallTwice > 0) || ShouldCallAtEnd)
   throw new AssertionException("ShouldCallFirst not first thod called");
  ShouldCallFirst = true;
 }

 public int ShouldCallTwice(string s) {
  if (!ShouldCallFirst)
   throw new AssertionException("ShouldCallTwice called before ShouldCallFirst");
  if (ShouldCallAtEnd)
   throw new AssertionException("ShouldCallTwice called after ShouldCallAtEnd");
  if (ShouldCallTwice >= 2)
   throw new AssertionException("ShouldCallTwice called more than twice");
  ShouldCallTwice++;
  return StringToInteger(s);
 }

 public void ShouldCallAtEnd() {
  if (!ShouldCallFirst)
   throw new AssertionException("ShouldCallAtEnd called before ShouldCallFirst");
  if (ShouldCallTwice != 2) throw new AssertionException("ShouldCallTwice not called twice");
  ShouldCallAtEnd = true;
 }

}

1

fake objectlà một triển khai thực sự của giao diện (giao thức) hoặc mở rộng bằng cách sử dụng kế thừa hoặc các phương pháp khác có thể được sử dụng để tạo - sự phụ thuộc. Thông thường nó được tạo bởi nhà phát triển như một giải pháp đơn giản nhất để thay thế một số phụ thuộc

stub objectlà một đối tượng trần (0, nil và các phương thức không có logic) với trạng thái bổ sung và được xác định trước (bởi nhà phát triển) để xác định các giá trị được trả về. Thông thường nó được tạo bởi khung

mock objectrất giống với stub objectnhưng trạng thái bổ sung được thay đổi trong khi thực hiện chương trình để kiểm tra xem có chuyện gì xảy ra không (phương thức được gọi).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.