2009-09-25 43 views
7

Tôi đang cố gắng tuân theo các phương pháp hay khi viết các bộ thử nghiệm của mình. Nửa chừng tôi nhận ra rằng iam chi tiêu rất nhiều (nhất) của thời gian của tôi trên các đối tượng Fake ... Hầu hết các thử nghiệm của tôi làm điều gì đó như thế nàyKiểm tra đơn vị với hàng giả hoặc mocks?

public interface ITemplateRepository 
{ 
    string get GetGenericTemplate {get;} 
} 


public FakeTemplateRepository : ITemplateRepository 
{ 
    public string GetGenericTemplate() 
    { 
    return "<xml>Complex</xml>"; 
    } 
} 


[Test] 
public void CanGetGenericTemplate() 
{ 
    ITemplateRepository rep = new FakeTemplateRepository(); 
    Assert.IsNotNull(rep.GetGenericTemplate()); 
} 


[Test] 
public void GetGenericTemplateContains() 
{ 
ITemplateRepository rep = new FakeTemplateRepository(); 
Assert.IsTrue(rep.GetGenericTemplate().StartsWith("<xml>")); 
} 

Tôi thực sự thấy mình dành rất nhiều thời gian trên FakeTemplateRepository, đảm bảo nó trả lại nội dung thực tế tôi đã mong đợi. đây là một điều xấu?

Đây có phải là Thử nghiệm đơn vị hợp lệ không? Thử nghiệm đơn vị phải nhanh chóng và đơn giản, phải không? Nhưng thành thực mà nói, tôi không chắc lắm, một điều chắc chắn là tôi nghĩ về hình dạng và nội dung dữ liệu của mình. Nội dung trong FakeRepository sẽ ít nhiều phản ánh nội dung sản xuất của tôi, mặc dù đọc từ hệ thống tệp, thay vì trong bộ nhớ.

Nếu thực tế những gì tôi đang làm là Kiểm tra tích hợp, thì tôi nên sử dụng mocks như thế nào cho các bài kiểm tra đơn vị của mình?

Nó không có ý nghĩa với tôi (nếu sử dụng Mocks) mà tôi đặt kỳ vọng lên để nó gọi phương thức và trả về một chuỗi? Tôi đang thiếu một cái gì đó nhưng tôi không thấy nhiều giá trị ở đó? Mã sẽ không biên dịch nếu tôi đặt tên phương thức không hợp lệ!

Tôi thực sự thực sự bối rối về toàn bộ sự việc và nhận thức của tôi về thử nghiệm đơn vị hoàn toàn bị mờ ngay bây giờ với tất cả các khái niệm này.

Bất kỳ ai có thể chứng minh bằng một ví dụ siêu siêu đơn giản về cách thức giả mạo và mô phỏng phù hợp với một bộ? Ví dụ: Thử nghiệm đơn vị là gì, thử nghiệm tích hợp là gì?

Cảm ơn

+0

Vâng, cho mã của bạn những gì nó muốn là sẽ không được rất hữu ích kể từ khi thử nghiệm ở dạng đơn giản nhất của nó là, tôi đoán, "đặt nó thông qua nó là dấu chân". –

Trả lời

9

Một lần nữa ... một người khác rơi vào mô hình chống giả. Bạn đang "thử nghiệm một mô hình" hoặc đối tượng giả - không phải là bất kỳ việc sử dụng nào cả. Mocks cần được sử dụng để trừu tượng hóa các phụ thuộc hoặc cộng tác viên của đối tượng thử nghiệm của bạn .. không phải là chủ thể thử nghiệm.

Trước tiên, tôi muốn đọc giấy Martin Fowler "Mocks Aren't Stubs". Nếu bạn muốn trả về các giá trị hoặc thiết lập kỳ vọng cho các đối số cụ thể, hãy tìm một khuôn khổ giả mạo trên hàng giả của riêng bạn. Hàng giả thường được sử dụng để phân phát các cộng tác viên ... nơi bạn không quan tâm đến cộng tác viên ... ví dụ: stub ra mạng hoặc tập tin IO.
Tiếp đọc this similar SO question và câu trả lời cho nó ..

2

Trước hết, học hỏi một khuôn khổ cô lập (chế giễu), như Moq hoặc Rhino Mocks. Điều này sẽ giúp bạn tiết kiệm rất nhiều thời gian.

Thứ hai, tránh tạo mocks bất cứ khi nào có thể và dính vào cuống. Sơ khai chỉ trả về giá trị; bạn không khẳng định họ. Thay vào đó, bạn khẳng định rằng trạng thái của lớp được thử nghiệm là những gì bạn mong đợi. Sử dụng cuống để loại bỏ các phụ thuộc tiêm.

Đây là một chủ đề phức tạp và bạn cần thực hiện một số việc đọc.Osherove's Art of Unit Testing là giá rẻ trong hình thức e-book của nó, và làm một công việc khá tốt để giải thích điều này. Bạn cũng sẽ muốn đọc trên Dependency Injection.

Hãy nhớ rằng bạn không cần hàng giả, mock hoặc sơ khai để kiểm tra nhiều lớp học. Vấn đề là để kiểm tra hành vi công khai của lớp thực tế trong sự cô lập. Hàng giả chỉ đơn giản là một công cụ giúp bạn tách biệt lớp khỏi mọi phụ thuộc.

Ví dụ của bạn tập trung vào hàng giả, giao diện và thử nghiệm. Tập trung vào các lớp học được kiểm tra và hành vi mong muốn của nó.

Kiểm tra tích hợp cũng có giá trị; bạn có thể nối mọi thứ tới cơ sở dữ liệu thử nghiệm và đảm bảo rằng tất cả đều hoạt động. Chúng có xu hướng chậm, trái ngược với các bài kiểm tra đơn vị.

EDIT: Bây giờ tôi đang đọc Growing Object-Oriented Software, Guided by Tests và đặt câu hỏi về quan điểm "tránh mocks" của tôi. Nếu bạn có các đối tượng theo sau Tell, Don't Ask thì thử nghiệm trạng thái có thể khó khăn.

5

Trong ví dụ của bạn, bạn đang thử nghiệm giả mạo của mình. Bạn không thể hiểu được điều này, bởi vì nó không có ý nghĩa.

Dưới đây là ví dụ về cách bạn nên sử dụng giả. Bạn muốn đơn vị kiểm tra lớp DocumentGenerator. Lớp này xảy ra để sử dụng các dịch vụ của ITemplateRepository. Tuy nhiên, để kiểm tra đơn vị đúng DocumentGenerator bạn muốn đảm bảo nó không phụ thuộc vào bất kỳ dịch vụ bên ngoài nào. Vì vậy, bạn cung cấp DocumentGenerator với một ITemplateRepository giả sẽ trả về kết quả đóng hộp.

Đây là mã trông như thế nào.

public class DocumentGenerator 
{ 
    ITemplateRepository _repo; 

    DocumentGenerator(ITemplateRepository repo) 
    { 
    _repo = repo; 
    } 

    Doc GenerateDoc() 
    { 
    .... 
    _repo.GetGenericTemplate(); 
    .... 
    } 
} 


[Test] 
public void GenerateDocTest() 
{ 
    ITemplateRepository rep = new FakeTemplateRepository(); 
    DocumentGenerator docGenerator = new DocumentGenerator(rep); 
    Assert.IsNotNull(docGenerator.GenerateDoc()); 
} 

Các ý chính của ví dụ là bạn thử nghiệm một cái gì đó mà sử dụng giả. Bạn không thử nghiệm bản thân giả. Giả mạo tồn tại để điều bạn đang thử nghiệm không phụ thuộc vào thứ gì đó bên ngoài.

+0

Điều gì sẽ xảy ra nếu DocumentGenartor không chấp nhận một kho lưu trữ mà thay vào đó là một giá trị chuỗi của một cái gì đó được trả về từ kho lưu trữ? i.e.DocumentGenerator (mẫu chuỗi). Nếu tôi đã phải làm một cái gì đó như thế này thì nó có gợi ý rằng tôi đã thiết kế sai? –

+0

Nếu DocumentGenartor chỉ nhận một String thì bạn không cần đối tượng giả nào cả. Bạn chỉ cần tạo các đối tượng giả cho cộng tác viên mà đơn vị đang thử nghiệm thực sự sử dụng. –