Tôi đã đọc các bài viết khác nhau về chế độ nhạo báng và sơ khai trong thử nghiệm, bao gồm Mocks Ar't Arub của Martin Fowler , nhưng vẫn không hiểu sự khác biệt.
Tôi đã đọc các bài viết khác nhau về chế độ nhạo báng và sơ khai trong thử nghiệm, bao gồm Mocks Ar't Arub của Martin Fowler , nhưng vẫn không hiểu sự khác biệt.
Câu trả lời:
Sơ khai
Tôi tin rằng sự khác biệt lớn nhất là một sơ khai mà bạn đã viết với hành vi được xác định trước. Vì vậy, bạn sẽ có một lớp thực hiện sự phụ thuộc (rất có thể là lớp trừu tượng hoặc giao diện) mà bạn đang giả mạo cho mục đích thử nghiệm và các phương thức sẽ được đặt ra với các phản hồi đã đặt. Họ sẽ không làm bất cứ điều gì lạ mắt và bạn đã viết mã gốc cho nó bên ngoài bài kiểm tra của bạn.
Chế nhạo
Giả là một phần mà trong bài kiểm tra của bạn, bạn phải thiết lập với mong đợi của mình. Một bản giả không được thiết lập theo cách được xác định trước để bạn có mã thực hiện trong bài kiểm tra của mình. Giả định theo cách được xác định trong thời gian chạy vì mã đặt kỳ vọng phải chạy trước khi chúng làm bất cứ điều gì.
Sự khác biệt giữa Mocks và Stub
Các thử nghiệm được viết bằng giả thường theo một initialize -> set expectations -> exercise -> verify
mẫu để thử nghiệm. Trong khi sơ khai viết sẵn sẽ theo một initialize -> exercise -> verify
.
Sự tương đồng giữa Mocks và Stub
Mục đích của cả hai là loại bỏ kiểm tra tất cả các phụ thuộc của một lớp hoặc hàm để các kiểm tra của bạn tập trung hơn và đơn giản hơn trong những gì chúng đang cố gắng chứng minh.
Có một số định nghĩa về các đối tượng, không có thật. Thuật ngữ chung là kiểm tra gấp đôi . Thuật ngữ này bao gồm: giả , giả , còn sơ khai , giả .
Theo bài viết của Martin Fowler :
- Đối tượng giả được truyền xung quanh nhưng không bao giờ thực sự được sử dụng. Thông thường chúng chỉ được sử dụng để điền vào danh sách tham số.
- Các đối tượng giả thực sự có các triển khai làm việc, 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 (một cơ sở dữ liệu trong bộ nhớ là một ví dụ tố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.
Mocks vs Stub = Thử nghiệm hành vi so với thử nghiệm Nhà nước
Theo nguyên tắc Kiểm tra chỉ một điều trong mỗi bài kiểm tra , có thể có một số sơ khai trong một bài kiểm tra, nhưng nhìn chung chỉ có một bản giả.
Kiểm tra vòng đời với cuống:
Kiểm tra vòng đời với giả:
Cả thử nghiệm giả và sơ khai đều đưa ra câu trả lời cho câu hỏi: Kết quả là gì?
Thử nghiệm với giả cũng quan tâm: Làm thế nào đạt được kết quả?
Một cuống là một đối tượng giả đơn giản. Nó chỉ đảm bảo kiểm tra chạy trơn tru.
Một mock là một sơ khai thông minh hơn. Bạn xác minh bài kiểm tra của bạn đi qua nó.
Dưới đây là một mô tả của từng người theo sau với mẫu thế giới thực.
Dummy - chỉ là giá trị không có thật để đáp ứng API
.
Ví dụ : Nếu bạn đang thử nghiệm một phương thức của một lớp yêu cầu nhiều tham số bắt buộc trong hàm tạo không có tác dụng đối với thử nghiệm của bạn, thì bạn có thể tạo các đối tượng giả cho mục đích tạo các thể hiện mới của một lớp.
Fake - tạo một triển khai thử nghiệm của một lớp có thể có sự phụ thuộc vào một số cơ sở hạ tầng bên ngoài. (Đó là thông lệ tốt khi kiểm tra đơn vị của bạn KHÔNG thực sự tương tác với cơ sở hạ tầng bên ngoài.)
Ví dụ : Tạo triển khai giả để truy cập cơ sở dữ liệu, thay thế nó bằng
in-memory
bộ sưu tập.
Sơ khai - các phương thức ghi đè để trả về các giá trị được mã hóa cứng, còn được gọi là state-based
.
Ví dụ : Lớp kiểm tra của bạn phụ thuộc vào một phương thức
Calculate()
mất 5 phút để hoàn thành. Thay vì chờ trong 5 phút, bạn có thể thay thế triển khai thực sự của nó bằng sơ khai trả về các giá trị được mã hóa cứng; chỉ mất một phần nhỏ thời gian
Mock - rất giống với Stub
nhưng interaction-based
thay vì dựa trên nhà nước. Điều này có nghĩa là bạn không mong đợi Mock
trả về một số giá trị, nhưng giả sử rằng thứ tự cụ thể của các cuộc gọi phương thức được thực hiện.
Ví dụ: Bạn đang kiểm tra một lớp đăng ký người dùng. Sau khi gọi
Save
, nó nên gọiSendConfirmationEmail
.
Stubs
và Mocks
thực sự là các loại phụ của Mock
, cả trao đổi thực hiện thực tế với thực hiện thử nghiệm, nhưng vì những lý do cụ thể, khác nhau.
Trong khóa học Codechool.com , Rails tests for Zombies , họ đưa ra định nghĩa này về các điều khoản:
Sơ khai
Để thay thế một phương thức bằng mã trả về một kết quả được chỉ định.
Chế nhạo
Một sơ khai với một khẳng định rằng phương thức được gọi.
Vì vậy, như Sean Strenhaver đã mô tả trong câu trả lời của mình, sự khác biệt là các giả định đặt kỳ vọng (nghĩa là đưa ra các xác nhận, về việc chúng có được gọi hay không).
Sơ khai không thất bại bài kiểm tra của bạn, giả có thể.
Tôi nghĩ rằng câu trả lời đơn giản và rõ ràng hơn về câu hỏi này được đưa ra từ Roy Osherove trong cuốn sách Nghệ thuật kiểm tra đơn vị (trang 85)
Cách dễ nhất để nói rằng chúng ta đang đối phó với một sơ khai là nhận thấy rằng sơ khai không bao giờ có thể thất bại trong bài kiểm tra. Các khẳng định sử dụng thử nghiệm luôn luôn chống lại lớp đang thử nghiệm.
Mặt khác, thử nghiệm sẽ sử dụng một đối tượng giả để xác minh xem thử nghiệm có thất bại hay không. [...]
Một lần nữa, đối tượng giả là đối tượng chúng ta sử dụng để xem thử nghiệm thất bại hay không.
Điều đó có nghĩa là nếu bạn đang xác nhận chống lại giả, điều đó có nghĩa là bạn đang sử dụng giả như một bản giả, nếu bạn chỉ sử dụng giả để chạy thử mà không xác nhận rằng bạn đang sử dụng giả như một cuống.
Đọc tất cả các giải thích ở trên, hãy để tôi cố gắng cô đọng:
Một Mock chỉ là kiểm tra hành vi, đảm bảo các phương thức nhất định được gọi. Stub là phiên bản có thể kiểm tra (per se) của một đối tượng cụ thể.
Bạn có ý nghĩa gì theo cách của Apple?
Nếu bạn so sánh nó với gỡ lỗi:
Sơ khai giống như đảm bảo một phương thức trả về giá trị đúng
Mock giống như thực sự bước vào phương thức và đảm bảo mọi thứ bên trong đều chính xác trước khi trả về giá trị chính xác.
Sử dụng một mô hình tinh thần thực sự giúp tôi hiểu điều này, hơn là tất cả những lời giải thích và bài báo, điều đó không hoàn toàn "chìm đắm".
Hãy tưởng tượng con bạn có một tấm kính trên bàn và nó bắt đầu chơi với nó. Bây giờ, bạn sợ nó sẽ vỡ. Vì vậy, bạn đưa cho anh ta một tấm nhựa thay thế. Đó sẽ là một Mock (cùng hành vi, cùng giao diện, thực hiện "nhẹ nhàng" hơn).
Bây giờ, giả sử bạn không có thay thế nhựa, vì vậy bạn giải thích "Nếu bạn tiếp tục chơi với nó, nó sẽ bị hỏng!". Đó là một Stub , bạn đã cung cấp một trạng thái được xác định trước.
Một hình nộm sẽ là cái nĩa mà anh ta thậm chí không sử dụng ... và một Spy có thể giống như đưa ra lời giải thích giống như bạn đã sử dụng.
Tôi nghĩ rằng sự khác biệt quan trọng nhất giữa họ là ý định của họ.
Hãy để tôi cố gắng giải thích nó trong TẠI SAO còn sơ khai so với TẠI SAO giả
Giả sử tôi đang viết mã kiểm tra cho bộ điều khiển dòng thời gian công khai của khách hàng twitter của tôi
Đây là mã mẫu thử nghiệm
twitter_api.stub(:public_timeline).and_return(public_timeline_array)
client_ui.should_receive(:insert_timeline_above).with(public_timeline_array)
controller.refresh_public_timeline
Bằng cách viết giả, bạn khám phá mối quan hệ cộng tác của các đối tượng bằng cách xác minh sự mong đợi được đáp ứng, trong khi sơ khai chỉ mô phỏng hành vi của đối tượng.
Tôi khuyên bạn nên đọc bài viết này nếu bạn đang cố gắng để biết thêm về giả: http://jmock.org/oopsla2004.pdf
Rất rõ ràng và thiết thực:
Sơ khai: Một lớp hoặc đối tượng thực hiện các phương thức của lớp / đối tượng được làm giả và trả về luôn những gì bạn muốn.
Ví dụ trong JavaScript:
var Stub = {
method_a: function(param_a, param_b){
return 'This is an static result';
}
}
Mock: Giống như sơ khai, nhưng nó thêm một số logic "xác minh" khi một phương thức được gọi để bạn có thể chắc chắn rằng một số triển khai đang gọi phương thức đó.
Như @mLevan nói hãy tưởng tượng như một ví dụ rằng bạn đang kiểm tra một lớp đăng ký người dùng. Sau khi gọi Save, nó sẽ gọi SendConf ConfirmationEmail.
Một mã rất ngu ngốc Ví dụ:
var Mock = {
calls: {
method_a: 0
}
method_a: function(param_a, param_b){
this.method_a++;
console.log('Mock.method_a its been called!');
}
}
Slide này giải thích sự khác biệt chính rất tốt.
* Từ CSE 403 Bài 16, Đại học Washington (slide được tạo bởi "Marty Stepp")
Tôi thích lời giải thích được đưa ra bởi Roy Osherove [liên kết video] .
Mỗi lớp hoặc đối tượng được tạo là Fake. Đó là một Mock nếu bạn xác minh các cuộc gọi chống lại nó. Nếu không thì nó vẫn còn sơ khai.
hãy xem Kiểm tra nhân đôi:
Stub : Stub là một đối tượng chứa dữ liệu được xác định trước và sử dụng nó để trả lời các cuộc gọi trong các thử nghiệm. Chẳng hạn như : một đối tượng cần lấy một số dữ liệu từ cơ sở dữ liệu để đáp ứng với một cuộc gọi phương thức.
Mocks : Mocks là đối tượng đăng ký các cuộc gọi mà họ nhận được. Trong xác nhận thử nghiệm, chúng tôi có thể xác minh trên Mocks rằng tất cả các hành động dự kiến đã được thực hiện. Chẳng hạn như : một chức năng gọi dịch vụ gửi e-mail. để biết thêm chỉ cần kiểm tra này .
Một giả là một thuật ngữ chung có thể được sử dụng để mô tả một trong hai vẫn còn sơ khai hoặc một đối tượng giả (viết tay hay cách khác), vì cả hai đều trông giống như các đối tượng thực sự.
Việc giả mạo là sơ khai hay giả, tùy thuộc vào cách sử dụng trong thử nghiệm hiện tại. Nếu nó được sử dụng để kiểm tra sự tương tác (được khẳng định), thì đó là một đối tượng giả. Nếu không, nó vẫn còn sơ khai.
Fakes đảm bảo kiểm tra chạy trơn tru. Điều đó có nghĩa là người đọc bài kiểm tra trong tương lai của bạn sẽ hiểu hành vi của đối tượng giả, sẽ không cần đọc mã nguồn của nó (mà không cần phụ thuộc vào tài nguyên bên ngoài).
Kiểm tra chạy trơn tru có nghĩa là gì?
Forexample trong mã dưới đây:
public void Analyze(string filename)
{
if(filename.Length<8)
{
try
{
errorService.LogError("long file entered named:" + filename);
}
catch (Exception e)
{
mailService.SendEMail("admin@hotmail.com", "ErrorOnWebService", "someerror");
}
}
}
Bạn muốn kiểm tra phương thức mailService.SendEMail () , để làm điều đó bạn cần mô phỏng Ngoại lệ trong phương thức kiểm tra của mình, vì vậy bạn chỉ cần tạo lớp FakeSub của Fake Stub để mô phỏng kết quả đó, sau đó mã kiểm tra của bạn sẽ có thể kiểm tra phương thức mailService.SendEMail (). Như bạn thấy, bạn cần mô phỏng một kết quả từ một lớp ErrorService phụ thuộc bên ngoài khác.
Ngay từ các Mock Roles giấy , không phải đối tượng , bởi các nhà phát triển của jMock:
Sơ khai là các triển khai giả của mã sản xuất trả về kết quả đóng hộp. Các đối tượng giả hoạt động như các cuống, nhưng cũng bao gồm các xác nhận để xác định các tương tác của đối tượng đích với các đối tượng lân cận.
Vì vậy, sự khác biệt chính là:
Tóm lại, trong khi cũng cố gắng phân tán sự nhầm lẫn từ tiêu đề bài viết của Fowler : giả là cuống, nhưng chúng không chỉ là cuống .
Tôi đã đọc Nghệ thuật kiểm tra đơn vị , và tình cờ thấy định nghĩa sau:
Một giả là một thuật ngữ chung có thể được sử dụng để mô tả một trong hai vẫn còn sơ khai hoặc một đối tượng giả (viết tay hay cách khác), vì cả hai đều trông giống như các đối tượng thực sự. Việc giả mạo là sơ khai hay giả, tùy thuộc vào cách sử dụng trong thử nghiệm hiện tại. nếu nó được sử dụng để kiểm tra sự tương tác (được khẳng định), thì đó là một đối tượng giả . Nếu không, nó vẫn còn sơ khai .
Tôi đã xem qua bài viết thú vị này của chúBob The Little Mocker . Nó giải thích tất cả các thuật ngữ theo cách rất dễ hiểu, vì vậy nó hữu ích cho người mới bắt đầu. Bài viết của Martin Fowlers là một bài khó đọc đặc biệt là cho những người mới bắt đầu như tôi.
Sơ khai giúp chúng tôi chạy thử nghiệm. Làm sao? Nó cung cấp các giá trị giúp chạy thử nghiệm. Các giá trị này tự nó không có thật và chúng tôi đã tạo các giá trị này chỉ để chạy thử nghiệm. Ví dụ: chúng tôi tạo HashMap để cung cấp cho chúng tôi các giá trị tương tự với các giá trị trong bảng cơ sở dữ liệu. Vì vậy, thay vì tương tác trực tiếp với cơ sở dữ liệu, chúng tôi tương tác với Hashmap.
Mock là một đối tượng giả chạy thử nghiệm. nơi chúng tôi đặt khẳng định.
Xem ví dụ bên dưới về mô phỏng so với sơ khai sử dụng khung C # và Moq. Moq không có từ khóa đặc biệt cho Stub nhưng bạn cũng có thể sử dụng đối tượng Mock để tạo sơ khai.
namespace UnitTestProject2
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
[TestClass]
public class UnitTest1
{
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method calls Repository GetName method "once" when Id is greater than Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Once);
}
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method doesn't call Repository GetName method when Id is Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(0);
// Assert
mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Never);
}
/// <summary>
/// Test using Stub to Verify that GetNameWithPrefix method returns Name with a Prefix
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
{
// Arrange
var stubEntityRepository = new Mock<IEntityRepository>();
stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
.Returns("Stub");
const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
var entity = new EntityClass(stubEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
}
}
public class EntityClass
{
private IEntityRepository _entityRepository;
public EntityClass(IEntityRepository entityRepository)
{
this._entityRepository = entityRepository;
}
public string Name { get; set; }
public string GetNameWithPrefix(int id)
{
string name = string.Empty;
if (id > 0)
{
name = this._entityRepository.GetName(id);
}
return "Mr. " + name;
}
}
public interface IEntityRepository
{
string GetName(int id);
}
public class EntityRepository:IEntityRepository
{
public string GetName(int id)
{
// Code to connect to DB and get name based on Id
return "NameFromDb";
}
}
}
Quan điểm thử nghiệm còn sơ khai và Mock:
Stub là triển khai giả được thực hiện bởi người dùng theo cách tĩnh có nghĩa là trong Stub viết mã thực hiện. Vì vậy, nó không thể xử lý định nghĩa dịch vụ và điều kiện động, Thông thường, điều này được thực hiện trong khung JUnit mà không sử dụng khung mô phỏng.
Mock cũng là triển khai giả nhưng việc triển khai thực hiện theo cách năng động bằng cách sử dụng các khung Mocking như Mockito. Vì vậy, chúng ta có thể xử lý điều kiện và định nghĩa dịch vụ theo cách động, tức là các giả có thể được tạo động từ mã khi chạy. Vì vậy, bằng cách sử dụng giả, chúng ta có thể thực hiện Stub một cách linh hoạt.
Cộng với câu trả lời hữu ích, Một trong những điểm mạnh nhất của việc sử dụng Mocks so với Dự bị
Nếu cộng tác viên [mà mã chính phụ thuộc vào nó] không thuộc quyền kiểm soát của chúng tôi (ví dụ: từ thư viện của bên thứ ba), thì
trong trường hợp này, sơ khai khó viết hơn là giả .
Tôi đã sử dụng các ví dụ python trong câu trả lời của tôi để minh họa sự khác biệt.
Stub - Stubbing là một kỹ thuật phát triển phần mềm được sử dụng để thực hiện các phương thức của các lớp sớm trong vòng đời phát triển. Chúng được sử dụng phổ biến như giữ chỗ để thực hiện giao diện đã biết, trong đó giao diện được hoàn thiện hoặc được biết nhưng việc triển khai chưa được biết hoặc hoàn tất. Bạn bắt đầu với sơ khai, điều đó có nghĩa đơn giản là bạn chỉ viết định nghĩa của hàm xuống và để lại mã thực tế cho sau này. Ưu điểm là bạn sẽ không quên các phương thức và bạn có thể tiếp tục suy nghĩ về thiết kế của mình trong khi xem nó trong mã. Bạn cũng có thể để sơ khai của bạn trả về một phản hồi tĩnh để các phản hồi có thể được sử dụng bởi các phần khác trong mã của bạn ngay lập tức. Các đối tượng còn sơ khai cung cấp một phản hồi hợp lệ, nhưng nó tĩnh cho dù bạn nhập thông tin nào, bạn sẽ luôn nhận được cùng một phản hồi:
class Foo(object):
def bar1(self):
pass
def bar2(self):
#or ...
raise NotImplementedError
def bar3(self):
#or return dummy data
return "Dummy Data"
Các đối tượng giả được sử dụng trong các trường hợp thử nghiệm giả, chúng xác nhận rằng các phương thức nhất định được gọi trên các đối tượng đó. Các đối tượng giả là các đối tượng mô phỏng bắt chước hành vi của các đối tượng thực theo các cách được kiểm soát. Bạn thường tạo một đối tượng giả để kiểm tra hành vi của một số đối tượng khác. Mocks cho phép chúng tôi mô phỏng các tài nguyên không có sẵn hoặc quá khó sử dụng để thử nghiệm đơn vị.
mymodule.py:
import os
import os.path
def rm(filename):
if os.path.isfile(filename):
os.remove(filename)
kiểm tra:
from mymodule import rm
import mock
import unittest
class RmTestCase(unittest.TestCase):
@mock.patch('mymodule.os')
def test_rm(self, mock_os):
rm("any path")
# test that rm called os.remove with the right parameters
mock_os.remove.assert_called_with("any path")
if __name__ == '__main__':
unittest.main()
Đây là một ví dụ rất cơ bản chỉ chạy rm và xác nhận tham số mà nó được gọi. Bạn có thể sử dụng giả với các đối tượng không chỉ là các chức năng như được hiển thị ở đây và bạn cũng có thể trả về một giá trị để có thể sử dụng một đối tượng giả để thay thế một sơ khai để kiểm tra.
Thông tin thêm về unittest.mock , lưu ý trong python 2.x mock không được bao gồm trong unittest nhưng là một mô-đun có thể tải xuống có thể được tải xuống qua pip (pip install mock).
Tôi cũng đã đọc "Nghệ thuật kiểm tra đơn vị" của Roy Osherove và tôi nghĩ sẽ thật tuyệt nếu một cuốn sách tương tự được viết bằng các ví dụ Python và Python. Nếu ai biết về một cuốn sách như vậy xin vui lòng chia sẻ. Chúc mừng :)
Sơ khai là một đối tượng giả được xây dựng cho mục đích thử nghiệm. Mock là một sơ khai ghi lại liệu các cuộc gọi dự kiến có hiệu quả hay không.
Sơ khai là một chức năng trống được sử dụng để tránh các ngoại lệ chưa được xử lý trong các thử nghiệm:
function foo(){}
Giả là một chức năng nhân tạo được sử dụng để tránh phụ thuộc vào hệ điều hành, môi trường hoặc phần cứng trong các thử nghiệm:
function foo(bar){ window = this; return window.toString(bar); }
Về mặt khẳng định và nhà nước:
Người giới thiệu
Có rất nhiều câu trả lời hợp lệ trên đó nhưng tôi nghĩ đáng để đề cập đến hình thức này chú bob: https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html
lời giải thích tốt nhất từng có với các ví dụ!
Một giả là cả một đối tượng kỹ thuật và chức năng .
Các giả là kỹ thuật . Nó thực sự được tạo ra bởi một thư viện giả (EasyMock, JMockit và gần đây là Mockito được biết đến với những thứ này) nhờ vào việc tạo mã byte .
Việc thực hiện mô hình được tạo ra theo một cách mà chúng ta có thể cụ nó để trả về một giá trị cụ thể khi một phương pháp được gọi nhưng cũng có một số thứ khác như xác minh rằng một phương pháp mô hình được gọi với một số thông số cụ thể (kiểm tra nghiêm ngặt) hoặc bất cứ thông số ( không kiểm tra nghiêm ngặt).
Khởi tạo một bản giả:
@Mock Foo fooMock
Ghi lại một hành vi:
when(fooMock.hello()).thenReturn("hello you!");
Xác minh một lời mời:
verify(fooMock).hello()
Đây rõ ràng không phải là cách tự nhiên để khởi tạo / ghi đè lớp / hành vi Foo. Đó là lý do tại sao tôi đề cập đến một khía cạnh kỹ thuật.
Nhưng giả cũng có chức năng vì nó là một thể hiện của lớp mà chúng ta cần tách ra khỏi SUT. Và với các hành vi được ghi lại trên đó, chúng ta có thể sử dụng nó trong SUT theo cách tương tự như chúng ta sẽ làm với một sơ khai.
Sơ khai chỉ là một đối tượng chức năng : đó là một thể hiện của lớp mà chúng ta cần tách ra khỏi SUT và đó là tất cả. Điều đó có nghĩa là cả lớp sơ khai và tất cả các đồ đạc hành vi cần thiết trong các bài kiểm tra đơn vị của chúng tôi phải được xác định rõ ràng.
Ví dụ để stub hello()
sẽ cần phải phân Foo
lớp lớp (hoặc thực hiện giao diện của nó, nó có nó) và ghi đè hello()
:
public class HelloStub extends Hello{
public String hello {
return "hello you!";
}
}
Nếu một kịch bản thử nghiệm khác yêu cầu trả về giá trị khác, có lẽ chúng ta sẽ cần xác định một cách chung để đặt trả về:
public class HelloStub extends Hello{
public HelloStub(String helloReturn){
this.helloReturn = helloReturn;
}
public String hello {
return helloReturn;
}
}
Kịch bản khác: nếu tôi có một phương thức hiệu ứng phụ (không trả về) và tôi sẽ kiểm tra xem phương thức đó có được gọi hay không, tôi có lẽ nên thêm một boolean hoặc một bộ đếm trong lớp sơ khai để đếm số lần phương thức được gọi.
Phần kết luận
Sơ khai đòi hỏi nhiều chi phí / mã để viết cho bài kiểm tra đơn vị của bạn. Những gì giả ngăn cản nhờ cung cấp các tính năng ghi / xác minh ra khỏi hộp.
Đó là lý do tại sao ngày nay, phương pháp sơ khai hiếm khi được sử dụng trong thực tế với sự ra đời của các thư viện giả tuyệt vời.
Về Điều Martin Fowler: Tôi không nghĩ là một lập trình viên "nhạo báng" trong khi tôi sử dụng giả và tôi tránh sơ khai.
Nhưng tôi sử dụng giả khi thực sự cần thiết (phụ thuộc gây khó chịu) và tôi thích kiểm tra cắt lát và kiểm thử tích hợp mini khi tôi kiểm tra một lớp với các phụ thuộc mà chế độ chế nhạo sẽ là chi phí chung.