2012-07-24 42 views
6

Tôi muốn giả lập Microsoft.Office.Interop.Excel.Range (và các giao diện Microsoft.Office.Interop.Excel khác) để kiểm tra đơn vị ứng dụng của tôi. Tôi đang sử dụng Moq 4.0.10827 với .NET 4 trong C#.Làm thế nào để giả lập Microsoft.Office.Interop.Excel.Range với Moq?

Trong thử nghiệm đơn vị của tôi, tôi cố gắng để thiết lập hành vi của các mô hình như sau:

 var range = new Mock<Microsoft.Office.Interop.Excel.Range>(); 
     range.Setup(r => r.get_Value(1)).Returns("Something"); 

     var classBeingTested = new MyClass(range.Object); 

Trong mã là đơn vị thử nghiệm, tôi đang sử dụng dãy như sau:

public MyClass(Range range) 
    { 
     var value = range[1].ToString(); 
    } 

Khi thử nghiệm chạy, nó tạo ra các ngoại lệ sau đây:

 Error: Missing method 'instance object [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get__Default(object,object)' from class 'Castle.Proxies.RangeProxy'. 

Làm thế nào tôi có thể thực hiện mockin này g thành công? Tôi nhận ra rằng cô lập chức năng Interop của Excel với một mẫu như https://stackoverflow.com/a/9486226/1548950 là một giải pháp tiềm năng; tuy nhiên, tôi sẽ hạnh phúc hơn khi có thể tạo ra các mocks từ giao diện Microsoft.Office.Interop.Excel.

EDIT: Xem thêm chi tiết về vấn đề này

OK, đây là kỳ lạ. Tôi đã tạo một dự án để kiểm tra đề xuất của jimmy_keen. Nó hoạt động. Tuy nhiên, khi tôi sử dụng đề nghị tương tự để kiểm tra các dự án tôi có vấn đề với, nó ném ngoại lệ sau đây:

Error: Missing method 'instance object [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get__Default(object,object)' from class 'Castle.Proxies.RangeProxy'. 

Kể từ gợi ý jimmy_keen của hoạt động tốt trên các dự án khác, tôi bắt đầu nghi ngờ rằng có cái gì đó sai với Tôi đang thử nghiệm mã với. Vì vậy, tôi đã tạo ra một dung dịch thử đó chứng tỏ vấn đề một cách chi tiết: http://www7.zippyshare.com/v/70834394/file.html

Gốc của vấn đề dường như là dự án chứa một lớp (có nghĩa là không được đơn vị được kiểm tra) với chủ yếu các mã sau:

using Microsoft.Office.Interop.Excel; 
namespace Project 
{ 
    public class UnTestedClass 
    { 
     public UnTestedClass(Worksheet sheet) 
     { 
      var foo = sheet.Range["Description"].Column; 
     } 
    } 
} 

Tôi không hiểu tại sao điều này gây ra sự cố, vì tôi không sử dụng UnTestedClass trong bài kiểm tra đơn vị. Tôi có thiếu một cái gì đó trong cách tôi nên sử dụng Moq, hoặc có tôi stumbled khi một lỗi?

+0

+1 Điều này thật lạ, tôi đoán nó có liên quan đến các đối tượng COM. Ngay sau khi tôi tham khảo các interop excel, tôi không còn có thể tham khảo thư viện Moq của tôi ... Weird ... – jsmith

+0

Sau khi một số công việc về điều này, tôi bây giờ di chuyển theo hướng cô lập các chức năng Microsoft.Office.Interop.Excel với của riêng tôi các lớp và giao diện tùy chỉnh thay vì chế nhạo Microsoft.Office.Interop.Excel. * trực tiếp. Trong khi câu trả lời cho câu hỏi này không giải quyết được các vấn đề trước mắt, hãy mocking Microsoft.Office.Interop.Excel. * Cuối cùng chỉ mới bắt đầu yêu cầu quá nhiều công việc thiết lập để làm cho nó hữu ích. –

Trả lời

5

Mã của bạn truy cập indexer, và đó là những gì bạn cần để chế nhạo:

var range = new Mock<Microsoft.Office.Interop.Excel.Range>(); 
range.Setup(r => r[1, It.IsAny<object>()]).Returns("something"); 

Lưu ý rằng Range indexer thực sự có hai tham số - vì thế It.IsAny<object>() hạn chế trong cuộc gọi.

+0

Cảm ơn, tôi đã thử nghiệm điều này và nó hoạt động trong một số trường hợp. Tuy nhiên, bài kiểm tra đơn vị tôi đang làm vẫn kiên quyết từ chối làm việc. Vui lòng xem giải pháp thử nghiệm mà tôi đã tải lên tại http://www7.zippyshare.com/v/70834394/file.html –

+2

@LauriHarpf: điều này thật thú vị. Rõ ràng đó là một "vấn đề" với trình biên dịch tạo ra mã.Giao diện kiểu 'Range' được tạo bởi trình biên dịch trong * Project * của bạn có thêm thuộc tính (' Column', cụ thể là). Tôi không biết đầu mối này có thể có vấn đề gì với Lâu đài ... nhưng đó là COM. Nếu bạn sẽ kiểm tra hội đồng của bạn với ILSpy ví dụ, bạn sẽ thấy những gì tôi có ý nghĩa. Trình biên dịch tạo ra mã khác (thậm chí các lớp tho đều giống nhau) và điều này phải là vấn đề. Lưu ý rằng nếu bạn stub 'range.Setup (r => r.Column) .Returns (0);' test này cũng sẽ vượt qua. –

+1

Tuyệt vời, cảm ơn! Mũi ILSpy cũng có màu vàng; trong dự án thực sự của tôi, tôi thấy các thuộc tính phụ khác xuất hiện ngoài Cột. Hiện tại là "Cột", "Cột", "Hàng", "Hàng" và "Giá trị". Hành vi này có thể làm cho bất kỳ bài kiểm tra đơn vị nào tôi viết khá giòn, bởi vì bất cứ lúc nào thuộc tính mới có thể xuất hiện và phá vỡ điều gì đó .. Trong mọi trường hợp, bằng cách sử dụng lời khuyên của bạn và cẩn thận chế giễu tất cả các thuộc tính bổ sung này hoạt động, để đánh dấu là câu trả lời. Cảm ơn ngài! –

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