2013-03-25 35 views
15

Tôi muốn thử nghiệm các dòng mã sau đây:Mocking HttpPostedFileBase và InputStream cho đơn vị kiểm tra

... 
Bitmap uploadedPicture = Bitmap.FromStream(model.Picture.InputStream) as Bitmap; 
... 

Ảnh là một tài sản trong loại mô hình của tôi HttpPostedFileBase. Vì vậy, tôi muốn giả lập thuộc tính HttpPostedFileBase để kiểm tra đơn vị:

model.Picture = new Mock<HttpPostedFileBase>().Object; 

Không sao cả.

Bây giờ tôi phải thử InputStream, nếu không nó là null:

model.Picture.InputStream = new Mock<Stream>().Object; 

này không hoạt động như InputStream là read-only (có không phải là một phương pháp setter):

public virtual Stream InputStream { get; } 

Có cách nào tốt và sạch sẽ để xử lý vấn đề này không? Một giải pháp sẽ là ghi đè lên HttpPostedFileBase trong một lớp dẫn xuất cho phép thử đơn vị của tôi. Bất kỳ ý tưởng nào khác?

Trả lời

29

Chào bạn :) Tôi đã làm một cái gì đó như thế nào,

[TestInitialize] 
    public void SetUp() 
    { 
     _stream = new FileStream(string.Format(
         ConfigurationManager.AppSettings["File"], 
         AppDomain.CurrentDomain.BaseDirectory), 
        FileMode.Open); 

     // Other stuff 
    } 

Và trên thử nghiệm bản thân,

[TestMethod] 
    public void FileUploadTest() 
    { 
     // Other stuff 

     #region Mock HttpPostedFileBase 

     var context = new Mock<HttpContextBase>(); 
     var request = new Mock<HttpRequestBase>(); 
     var files = new Mock<HttpFileCollectionBase>(); 
     var file = new Mock<HttpPostedFileBase>(); 
     context.Setup(x => x.Request).Returns(request.Object); 

     files.Setup(x => x.Count).Returns(1); 

     // The required properties from my Controller side 
     file.Setup(x => x.InputStream).Returns(_stream); 
     file.Setup(x => x.ContentLength).Returns((int)_stream.Length); 
     file.Setup(x => x.FileName).Returns(_stream.Name); 

     files.Setup(x => x.Get(0).InputStream).Returns(file.Object.InputStream); 
     request.Setup(x => x.Files).Returns(files.Object); 
     request.Setup(x => x.Files[0]).Returns(file.Object); 

     _controller.ControllerContext = new ControllerContext(
           context.Object, new RouteData(), _controller); 

     // The rest... 
    } 

Hy vọng điều này có thể cung cấp một ý tưởng giải pháp của bạn :)

+1

Tôi đã làm nó khá giống nên tôi đánh dấu câu trả lời của bạn là chính xác. – mosquito87

11

tôi đã chỉ làm việc trên một cái gì đó tương tự và muốn thêm những điều sau đây để trả lời @ TiagoC13 của.

Hệ thống của tôi đang thử nghiệm là dịch vụ tệp tôi đang viết, một trong những yêu cầu để kiểm tra xem tệp có kích thước chính xác hay không. Lưu ý, tên tệp được mã hóa cứng. Điều này tồn tại như một thư mục và tập tin trong dự án thử nghiệm của tôi. Các thuộc tính của tệp như sau: Xây dựng Hành động: Tài nguyên Nhúng và Sao chép vào Thư mục Đầu ra: Sao chép nếu mới hơn (mặc dù Sao chép Luôn hoạt động OK)

Khi dự án được xây dựng testimage.jpg và thư mục của nó được thêm vào thùng nơi thử nghiệm sau đó tìm thấy nó.

Cũng lưu ý tệpStream.Close(); điều này giải phóng tệp để bạn có thể có một số thử nghiệm tương tự trong cùng một bộ.

Hy vọng đây là trợ giúp.

using Moq; 
using NUnit.Framework; 
using System.Web; 

    [Test] 
    public void IsValidFile() { 
     string filePath = Path.GetFullPath(@"testfiles\testimage.jpg"); 
     FileStream fileStream = new FileStream(filePath, FileMode.Open); 
     Mock<HttpPostedFileBase> uploadedFile = new Mock<HttpPostedFileBase>(); 

     uploadedFile 
      .Setup(f => f.ContentLength) 
      .Returns(10); 

     uploadedFile 
      .Setup(f => f.FileName) 
      .Returns("testimage.jpg"); 

     uploadedFile 
      .Setup(f => f.InputStream) 
      .Returns(fileStream); 

     var actual = fileSystemService.IsValidImage(uploadedFile.Object, 720, 960); 

     Assert.That(actual, Is.True); 

     fileStream.Close(); 
    } 
+1

nó đã giúp tôi :) –

7

Không cần tạo luồng từ việc mở tệp trên đĩa. Thực ra tôi nghĩ đó là một giải pháp khá khủng khiếp. Một dòng thử nghiệm làm việc có thể được tạo ra một cách dễ dàng đủ trong bộ nhớ.

var postedFile = new Mock<HttpPostedFileBase>(); 

using (var stream = new MemoryStream()) 
using (var bmp = new Bitmap(1, 1)) 
{ 
    var graphics = Graphics.FromImage(bmp); 
    graphics.FillRectangle(Brushes.Black, 0, 0, 1, 1); 
    bmp.Save(stream, ImageFormat.Jpeg); 

    postedFile.Setup(pf => pf.InputStream).Returns(stream); 

    // Assert something with postedFile here 
}   
+2

Điều này trở thành một bài kiểm tra đơn vị thay vì một bài kiểm tra tích hợp như giải pháp của Daniel. Thật tuyệt, tôi không biết bạn có thể kéo cái này ra như thế này, nhưng cái này ít dễ đọc hơn (mặc dù tôi đồng ý bạn có thể sử dụng lại mã trong các bài kiểm tra của bạn). Không chắc những gì quá khủng khiếp về người khác ngoài việc phải có một hình ảnh trong dự án thử nghiệm. Nó không tệ hơn là có một cơ sở dữ liệu cho các bài kiểm tra tích hợp ... –

+0

@fearofawhackplanet rất đẹp! – csharpsql

+1

@FabioMilheiro thật khủng khiếp vì OP đặc biệt hỏi về thử nghiệm đơn vị và kiểm tra đơn vị không nên phụ thuộc vào hệ thống tệp vật lý. – fearofawhackplanet