Câu hỏi của bạn là về cách khung MS Fakes khác với NMock và có vẻ như các câu trả lời khác đã giải quyết một số vấn đề đó, nhưng đây là một số thông tin khác về cách chúng giống nhau và chúng khác nhau như thế nào. NMock cũng tương tự như RhinoMocks và Moq, vì vậy tôi đang nhóm chúng lại với NMock.
Có 3 điểm khác biệt chính mà tôi thấy ngay giữa NMock / RhinoMocks / Moq và MS Fakes Framework:
Khung công tác giả mạo MS sử dụng mã được tạo, giống như Trình truy cập trong các phiên bản trước của Visual Studio thay vì các loại chung chung. Khi bạn muốn sử dụng khung giả mạo cho một phần phụ thuộc, bạn thêm hợp ngữ chứa phần phụ thuộc vào các tham chiếu của dự án thử nghiệm và sau đó nhấp chuột phải vào nó để tạo các bản sao thử nghiệm (sơ khai hoặc miếng chêm). Sau đó, khi bạn đang kiểm tra, bạn thực sự đang sử dụng các lớp được tạo này để thay thế. NMock sử dụng generic để thực hiện điều tương tự (tức là IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). Theo ý kiến của tôi, cách tiếp cận khung MS Fakes hạn chế điều hướng mã và cấu trúc lại từ bên trong các thử nghiệm vì bạn thực sự đang làm việc với một lớp được tạo chứ không phải giao diện thực của bạn.
Khung làm việc giả mạo MS cung cấp sơ khai và nốt ruồi (miếng chêm), trong khi NMock, RhinoMocks và Moq đều cung cấp sơ khai và mô phỏng . Tôi thực sự không hiểu quyết định của MS khi không bao gồm những lời chế giễu và cá nhân tôi không phải là một fan hâm mộ của nốt ruồi vì những lý do được mô tả dưới đây.
Với khung công tác giả mạo MS, bạn cung cấp một triển khai thay thế của các phương pháp bạn muốn sơ khai. Trong các triển khai thay thế này, bạn có thể chỉ định các giá trị trả về và theo dõi thông tin về cách hoặc nếu phương thức được gọi. Với NMock, RhinoMocks và Moq, bạn tạo một đối tượng mô phỏng và sau đó sử dụng đối tượng đó để chỉ định các giá trị trả về sơ khai hoặc để theo dõi các tương tác (liệu các phương thức có được gọi hay không). Tôi thấy cách tiếp cận giả mạo MS phức tạp hơn và ít biểu đạt hơn.
Để làm rõ sự khác biệt về những gì các khung công tác cung cấp: NMock, RhinoMocks và Moq đều cung cấp hai loại thử nghiệm kép (sơ khai và mô phỏng). Khuôn khổ giả mạo cung cấp các phần khai và nốt ruồi (họ gọi chúng là miếng chêm) và không may là không bao gồm các phần giả. Để hiểu được sự khác biệt và giống nhau giữa NMock và MS Fakes, sẽ rất hữu ích nếu bạn hiểu các loại bộ đôi thử nghiệm khác nhau này là gì:
Stubs: Stubs được sử dụng khi bạn cần cung cấp giá trị cho các phương thức hoặc thuộc tính sẽ được yêu cầu nhân đôi thử nghiệm của bạn theo phương pháp đang thử nghiệm. Ví dụ: khi phương thức của tôi đang được thử nghiệm gọi phương thức DoesStudentExist () của thử nghiệm IStudentRepository kép, tôi muốn nó trả về true.
Ý tưởng về sơ khai trong NMock và MS giả là giống nhau, nhưng với NMock, bạn sẽ làm điều gì đó như sau:
Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));
Và với MSFakes, bạn sẽ thực hiện một số cách như thế này:
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
Lưu ý rằng trong ví dụ MS Fakes, bạn tạo một triển khai hoàn toàn mới cho phương thức DoesStudentExist (Lưu ý rằng nó được gọi là DoesStudentExistInt32 vì khuôn khổ giả mạo gắn các kiểu dữ liệu tham số vào tên phương thức khi nó tạo ra các đối tượng sơ khai, tôi nghĩ điều này che khuất sự rõ ràng của Các bài kiểm tra). Thành thật mà nói, việc triển khai NMock cũng làm tôi khó chịu vì nó sử dụng một chuỗi để xác định tên phương thức. (Thứ lỗi cho tôi nếu tôi đã hiểu lầm cách NMock được dự định sử dụng.) Cách tiếp cận này thực sự hạn chế việc tái cấu trúc và tôi thực sự khuyên bạn nên sử dụng RhinoMocks hoặc Moq thay vì NMock vì lý do này.
Mocks: Mocks được sử dụng để xác minh sự tương tác giữa phương pháp của bạn đang được thử nghiệm và các phụ thuộc của nó. Với NMock, bạn thực hiện điều này bằng cách đặt các kỳ vọng tương tự như sau:
Expect.Once.On(mockStudentRepository).Method("Find").With(123);
Đây là một lý do khác tại sao tôi thích RhinoMocks và Moq hơn NMock, NMock sử dụng kiểu kỳ vọng cũ hơn trong khi RhinoMocks và Moq đều hỗ trợ cách tiếp cận Sắp xếp / Hành động / Khẳng định trong đó bạn chỉ định các tương tác mong đợi dưới dạng xác nhận ở cuối thử nghiệm như thế này :
stubStudentRepository.AssertWasCalled( x => x.Find(123));
Một lần nữa, hãy lưu ý rằng RhinoMocks sử dụng lambda thay vì một chuỗi để xác định phương thức. Khung công tác giả mạo ms hoàn toàn không cung cấp mô hình giả. Điều này có nghĩa là trong các triển khai sơ khai của bạn (xem mô tả sơ khai ở trên), bạn phải đặt các biến mà sau này bạn xác minh đã được đặt đúng chưa. Nó sẽ trông giống như thế này:
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
Tôi thấy cách tiếp cận này hơi phức tạp vì bạn phải theo dõi lệnh gọi trong sơ khai và sau đó xác nhận nó sau này trong thử nghiệm. Tôi thấy các ví dụ về NMock, và đặc biệt là RhinoMocks trở nên biểu cảm hơn.
Nốt ruồi (Shims): Thành thật mà nói, tôi không thích nốt ruồi, vì chúng có khả năng bị lợi dụng. Một trong những điều tôi rất thích về kiểm thử đơn vị (và đặc biệt là TDD) là kiểm tra mã của bạn sẽ giúp bạn hiểu nơi bạn đã viết mã kém. Điều này là do việc kiểm tra mã được viết kém rất khó. Điều này không đúng khi sử dụng nốt ruồi vì nốt ruồi thực sự được thiết kế để cho phép bạn kiểm tra sự phụ thuộc không được tiêm hoặc để kiểm tra các phương pháp riêng tư. Chúng hoạt động tương tự như sơ khai, ngoại trừ việc bạn sử dụng ShimsContext như sau:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
Lo lắng của tôi với miếng chêm là mọi người sẽ bắt đầu coi chúng là "cách dễ dàng hơn để kiểm tra đơn vị" bởi vì nó không buộc bạn phải viết mã theo cách bạn nên làm. Để viết đầy đủ hơn về khái niệm này, hãy xem bài đăng này của tôi:
Để biết thêm thông tin về một số mối quan tâm liên quan đến khuôn khổ hàng giả, hãy xem các bài đăng sau:
Nếu bạn quan tâm đến việc học RhinoMocks, đây là video đào tạo Pluralsight (tiết lộ đầy đủ - tôi đã viết khóa học này và được trả tiền bản quyền cho lượt xem, nhưng tôi nghĩ nó áp dụng cho cuộc thảo luận này nên tôi sẽ đưa nó vào đây):