2009-08-11 55 views
19

Trước hết, Tôi biết rằng câu hỏi này là nguy hiểm gần: How to MapPath in a unit test in C#C# đơn vị kiểm tra: Kiểm tra một phương pháp có sử dụng MapPath

Tôi hy vọng tuy nhiên, nó có một giải pháp khác nhau. Vấn đề của tôi sau:

Trong mã của tôi, tôi có một đối tượng cần được xác thực. Tôi đang tạo các bài kiểm tra đơn vị cho từng phương pháp xác thực để đảm bảo rằng nó đang xác thực chính xác. Tôi đang tạo dữ liệu giả và tải nó vào đối tượng, sau đó xác nhận nó. Vấn đề là trong quá trình xác nhận, khi một lỗi xảy ra, một mã lỗi được gán. Mã lỗi này được sử dụng để thu thập thông tin về lỗi từ tệp xml bằng cách sử dụng Server.MapPath. Tuy nhiên, khi cố gắng lấy tệp xml, một ngoại lệ được ném có nghĩa là không thể tìm thấy tệp.

Vì MapPath nằm trong mã xác nhận của tôi chứ không phải kiểm tra đơn vị của tôi, làm cách nào để kiểm tra đơn vị của tôi nhận ra đường dẫn? Câu hỏi này có hợp lý không?

Error Line (Trong mã Validation tôi KHÔNG thử nghiệm đơn vị của tôi):

XDocument xdoc = XDocument.Load(HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml")); 

Giản: Các Unit Test gọi một phương pháp trong chương trình của tôi mà các cuộc gọi Server.MapPath mà sau đó thất bại.

Trả lời

15

Tôi sẽ trừu tượng ra "nhà cung cấp tên tệp" vào một lớp đơn giản trả về một vị trí, sau đó bạn có thể thử nhiều, dễ dàng hơn nhiều.

public class PathProvider 
{ 
    public virtual string GetPath() 
    { 
     return HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml"); 
    } 
} 

Sau đó, bạn có thể sử dụng lớp PathProvider trực tiếp ...

PathProvider pathProvider = new PathProvider(); 
XDocument xdoc = XDocument.Load(pathProvider.GetPath()); 

Hoặc thử nó ra trong các thử nghiệm của bạn:

PathProvider pathProvider = new MockPathProvider(); // using a mocking framework 
XDocument xdoc = XDocument.Load(pathProvider.GetPath()); 
+2

GetPath() có thể là ảo. – dahlbyk

+0

@Dan HttpContext.Current. trả về null khi chúng ta chạy từ TestProject. Bất kỳ cách nào để tránh điều này? –

+0

@JibinMathew Có, không sử dụng 'HttpContext.Current'. Tôi biết điều đó nghe có vẻ tinh tế nhưng đó là sự thật. Nói chung, không giả lập các lớp mà bạn không sở hữu, nhưng bạn có thể viết một lớp trình bao bọc cho 'HttpContextBase', thực hiện chức năng mong muốn của bạn. –

1

Hãy thử sử dụng tê giác Mocks hoặc một khung thay thế giả mạo để giả mạo httpContext (hoặc các đối tượng phụ thuộc khác) Hoặc bạn có thể viết đối tượng giả của riêng mình. Hoặc viết một lớp MapPathWrapper, kế thừa từ một lớp MapPathWrapperBase cho môi trường thực của bạn, sau đó trong các thử nghiệm đơn vị của bạn tạo ra một đối tượng MockMapPathWrapper.

Sẽ có rất nhiều ví dụ để mô phỏng trên SO.

Dưới đây là một tôi hỏi:

How to use Rhino Mocks to Mock an HttpContext.Application

CẬP NHẬT tôi chỉ có kinh nghiệm làm điều này với Asp.Net MVC, với webforms tôi imagein nó sẽ có rất nhiều khó khăn hơn do sự thiếu của lớp HttpContextBase.

1

tôi sẽ trích xuất các phương pháp mà chấp nhận sự phụ thuộc của bạn làm đối số:

public void Validate(HttpContext context) 
{ 
    ValidatePath(context.Server.MapPath("App_Data/ErrorCodes.xml")); 
} 

public void ValidatePath(string path) 
{ 
    XDocument xdoc = XDocument.Load(path); 
    ValidateDocument(xdoc); 
} 

public void ValidateDocument(XDocument xdoc) 
{ 
    // Original code 
} 

Sau đó bạn có thể kiểm tra các phương thức khác nhau một cách độc lập. Ví dụ: thử nghiệm cách ValidatePath() xử lý tệp bị thiếu.

11

Sau một số googling nghiêm ngặt và một số trợ giúp từ một đồng nghiệp, chúng tôi đã đưa ra một giải pháp đơn giản đã được tích hợp sẵn.net

Phía trên bài kiểm tra đơn vị đó truy cập vào quá trình xác minh, tôi nói thêm:

[TestMethod()] 
[HostType("ASP.NET")] 
[UrlToTest("http://localhost:###/upload_file.aspx")] 
[AspNetDevelopmentServerHost("Path To Web Application", "Path To Web Root")] 

này hoạt động hoàn hảo. Về cơ bản, khi thử nghiệm được gọi, nó sẽ tải URL với bài kiểm tra đơn vị được chỉ định trong tải trang. Vì nó là một trang web hiện đang gọi thử nghiệm đơn vị, việc xác thực sẽ có quyền truy cập vào Server.MapPath. Giải pháp này có thể không hiệu quả với mọi người, nhưng nó hoàn hảo cho việc này. Nhờ tất cả những gì bạn đã đóng góp.

+1

Các thử nghiệm tích hợp như thế này chắc chắn hữu ích để đảm bảo tất cả các phần hoạt động cùng nhau, nhưng có các kịch bản khác (như một tệp bị thiếu) mà giải pháp này sẽ không thể xử lý được. Việc tạo ra ứng dụng web thử nghiệm cũng là một hoạt động khá tốn kém, có thể tăng lên nếu bạn chạy thử nghiệm thường xuyên. – dahlbyk

+0

đồng ý, trong khi giải pháp này có một số công đức theo nghĩa rằng nó có thể cung cấp thông tin hữu ích khi chạy, nó không phải là một bài kiểm tra đơn vị trong bất kỳ ý nghĩa của từ và nó thiếu lợi ích nhất của các bài kiểm tra đơn vị thực tế. – kai

+0

đó là một tiết kiệm thời gian tuyệt vời !! – Luther