2013-05-23 30 views
6

Tôi đã nhìn thấy nhiều câu trả lời liên quan đến 'cách phân tích các lớp học của bạn để bạn có thể kiểm soát những gì xảy ra trong SUT'.C# stubbing. Giao diện cho mọi đối tượng có thể thử nghiệm?

Họ nói một điều:

Tạo một giao diện và tiêm giao diện sử dụng dependency injection và tạo ra một sơ khai sử dụng giao diện tương tự mà bạn sau đó tiêm vào SUT.

Tuy nhiên, những gì tôi đã học được ở những nơi làm việc trước đây của tôi:

Nếu bạn kiểm tra đơn vị, bạn kiểm tra tất cả các lớp/chức năng.

Điều đó có nghĩa là đối với mỗi lớp có bố cục chức năng cụ thể bạn phải tạo giao diện?

Điều đó có nghĩa là số lượng lớp/tệp sẽ lớn hơn gấp đôi.

Như đã thấy trong ví dụ bên dưới, đây có phải là 'cách để đi' hay tôi thiếu điều gì đó trong quy trình thử nghiệm đơn vị của tôi không?

Lưu ý: Tôi đang sử dụng Express VS2012. Điều đó có nghĩa là không có khuôn khổ 'Faker'. Tôi đang sử dụng khung kiểm thử đơn vị VS2012 'chuẩn'.

Là một ví dụ rất, rất đơn giản, cho phép tôi phân phát từng giao diện được chuyển xuống SUT.

IFoo.cs

public interface IFoo 
{ 
    string GetName(); 
} 

Foo.cs

public class Foo : IFoo 
{ 
    public string GetName() 
    { 
     return "logic goes here"; 
    } 
} 

IBar.cs:

public interface IBar : IFoo 
{ 
    IFoo GetFoo(); 
} 

Bar.cs:

public class Bar : IBar 
{ 
    public string GetName() 
    { 
     return "logic goes here"; 
    } 

    public IFoo GetFoo() 
    { 
     return null; // some instance of IFoo 
    } 
} 

IBaz.cs:

public interface IBaz 
{ 
    IBar GetBar(); 
} 

Baz.cs:

public class Baz 
{ 
    public IBar GetBar() 
    { 
     return null; // some instance of IBar 
    } 
} 
+3

Lời khuyên của tôi: tìm một khung mocking tốt (Moq là một lựa chọn tốt) không yêu cầu bạn tạo tất cả các giao diện đó. –

+0

Tôi sẽ xem xét khuôn khổ đó –

+1

@RobertHarvey: Moq sẽ giúp tránh tạo ra các giao diện như thế nào? OP vẫn cần phải để lại điểm vào cho nó (Moq), có thể là thành viên ảo hoặc giao diện. –

Trả lời

4

Có và không. Để phụ thuộc vào bạn cần một số loại trừu tượng, nhưng đó là đa số vì cách mocking framework work (không phải tất cả, một cách tự nhiên).

Hãy xem xét ví dụ đơn giản. Bạn kiểm tra lớp A sẽ phụ thuộc vào các lớp học BC. Đối với các bài kiểm tra đơn vị A để hoạt động, bạn cần giả lập BC - bạn sẽ cần IBIC (hoặc các lớp cơ sở/thành viên ảo w). Bạn có cần IA không? Không, ít nhất là không cho thử nghiệm này. Và trừ khi A trở thành phụ thuộc vào một số lớp khác, hãy đánh dấu trừu tượng sau giao diện/lớp cơ sở không bắt buộc.

Sự trừu tượng tuyệt vời vì nó giúp bạn xây dựng mã kết hợp hoàn toàn. Bạn nên trừu tượng phụ thuộc của bạn. Tuy nhiên, trong thực tế, một số lớp không cần phải trừu tượng khi chúng phục vụ các vai trò cấp cao nhất/cuối của phân cấp/gốc và không được sử dụng ở nơi khác.

+0

Vì vậy, bạn sẽ đi để làm cho các chức năng ảo thay vì sử dụng một giao diện (Trường hợp một giao diện là _not_ yêu cầu). Điều này có mang thêm hành vi không mong muốn không? Tôi sẽ không bận tâm đến các lớp con kế thừa từ các lớp của tôi và ghi đè mọi phương thức. –

+0

@DaanTimmer: Điều đó tùy thuộc vào từng loại cơ sở. Tuy nhiên, trong hầu hết các trường hợp, bạn muốn sử dụng giao diện. Lớp cơ sở và thừa kế thường khó nắm bắt hơn và kết quả là khó duy trì hơn thành phần (xem tại đây) (http://en.wikipedia.org/wiki/Composition_over_inheritance)). Tất nhiên, khi lớp cơ sở là hợp lý đó là những gì bạn nên làm. Một điểm nữa - nếu đối số duy nhất của bạn chống lại giao diện là "chúng sẽ tăng gấp đôi số kiểu", hơn là không có đối số nào cả. Bạn không nên từ bỏ thiết kế phù hợp cho lợi ích nhân tạo về số lượng/thống kê. –

+0

@DaanTimmer: Bên cạnh đó, việc mở lớp học của bạn như thế (làm cho các thành viên của nó ảo) hiếm khi là một ý tưởng hay, nhất là khi không có lý do chính đáng (và "ít kiểu" hơn không phải là một). –

3

Có lẽ từ góc độ purist đó là cách đúng đắn để đi, nhưng điều thực sự quan trọng là đảm bảo rằng các phụ thuộc bên ngoài (ví dụ cơ sở dữ liệu, truy cập mạng, vv), bất cứ thứ gì tốn kém về mặt tính toán/tốn thời gian và bất kỳ thứ gì không hoàn toàn xác định được trừu tượng và dễ dàng thay thế trong các bài kiểm tra đơn vị của bạn.

6

Theo ý kiến ​​của tôi, bạn không nên tạo giao diện chỉ nhằm mục đích kiểm thử đơn vị. Nếu bạn bắt đầu thêm abstractions mã để làm hài lòng các công cụ, thì chúng không giúp bạn làm việc hiệu quả hơn. Mã bạn viết lý tưởng nên phục vụ mục đích/nhu cầu kinh doanh cụ thể - trực tiếp hoặc gián tiếp bằng cách làm cho cơ sở mã dễ bảo trì hoặc phát triển hơn.

Giao diện đôi khi làm điều này, nhưng chắc chắn không phải lúc nào. Tôi thấy rằng việc cung cấp giao diện cho các thành phần thường là một điều tốt, nhưng cố gắng tránh sử dụng giao diện cho các lớp bên trong (tức là, mã chỉ được sử dụng bên trong của dự án đã cho, bất kể các loại được khai báo công khai hay không). Điều này là do một thành phần (như trong, một tập hợp các lớp làm việc cùng nhau để giải quyết một số vấn đề cụ thể) đại diện cho một khái niệm lớn hơn (chẳng hạn như trình ghi nhật ký hoặc trình lên lịch), cái mà tôi có thể muốn thay thế hoặc phân tích khi thử nghiệm .

Giải pháp (mũ tip cho Robert là lần đầu tiên trong các ý kiến) là sử dụng một khung mocking để tạo ra một loại thay thế tương thích tại thời gian chạy. Mocking frameworks cho phép bạn xác minh rằng lớp đang được kiểm tra tương tác chính xác với giả được thay thế. Moq là như đã đề cập một sự lựa chọn snazzy. Rhino.Mocks và NMock là hai khung công tác phổ biến khác. Typemock Isolator móc vào profiler và nằm trong số các tùy chọn mạnh mẽ hơn (cho phép bạn thay thế ngay cả các thành viên riêng tư không phải ảo), nhưng là một công cụ thương mại.

Không có quy tắc tạo nên tốt cho bao nhiêu bạn nên kiểm tra đơn vị. Nó phụ thuộc vào những gì bạn đang phát triển và mục tiêu của bạn là gì - nếu tính chính xác luôn luôn vượt thời gian để thị trường và chi phí không phải là một yếu tố thì đơn vị kiểm tra mọi thứ đều tuyệt vời. Hầu hết mọi người không may mắn và sẽ phải thỏa hiệp để đạt được mức độ kiểm tra hợp lý. Bao nhiêu bạn nên kiểm tra cũng có thể phụ thuộc vào mức độ kỹ năng tổng thể của nhóm, tuổi thọ dự kiến ​​và tái sử dụng mã được viết, v.v.

+0

Tôi may mắn không gặp vấn đề gì liên quan đến người quản lý và thời gian ra thị trường. Tôi chỉ là một nhà phát triển duy nhất làm điều này trong thời gian rảnh rỗi của tôi để tìm hiểu bản thân một số công cụ bổ sung mà tôi không thể học tại công việc của tôi (tại thời điểm này). (Am a Embedded S.E. sử dụng C tại thời điểm này, đôi khi lắp ráp, đôi khi C#, đôi khi C++) nên yeah. Bây giờ tôi chỉ đang tìm cách để thử nghiệm đơn vị C#. Trước đây đã làm rất nhiều thử nghiệm đơn vị trong Python (làm việc liên quan) –

0

Từ góc độ kiểm tra, không cần tạo giao diện cho mọi lớp trong mã. Bạn tạo một giao diện để che giấu việc thực thi cụ thể các phụ thuộc bên ngoài sau một lớp trừu tượng. Vì vậy, thay vì có một lớp đòi hỏi một kết nối HTTP trực tiếp trộn lẫn với logic của bạn, bạn sẽ tách mã kết nối thành một lớp, có nó thực hiện một giao diện là thành viên của lớp của bạn, và tiêm một mô hình vào vị trí pf mà giao diện . Bằng cách đó, bạn có thể kiểm tra logic của mình một cách độc lập, không phụ thuộc và mã "chưa được kiểm tra" duy nhất là mã kết nối HTTP có sẵn có thể được kiểm tra thông qua các phương tiện khác.

0

Tôi sẽ đi tuyến đường phương pháp ảo.Tạo giao diện cho mọi lớp bạn cần để kiểm tra trở nên thực sự nặng nề, đặc biệt là khi bạn cần các công cụ như Resharper cho "đi thực hiện" mỗi lần bạn muốn xem định nghĩa của một phương thức. Và có phí quản lý và sửa đổi cả hai tệp bất kỳ lúc nào một chữ ký phương thức được thay đổi hoặc một thuộc tính hoặc phương thức mới được thêm vào.

Các vấn đề liên quan