2012-05-23 29 views
12

Tôi đang cố gắng để Setup sự trở lại của một cuộc gọi đến một phương pháp mở rộng và đang nhận:Cài đặt kết quả cho cuộc gọi đến phương pháp khuyến nông

SetUp : System.NotSupportedException : Expression references a method that does not belong to the mocked object: m => m.Cache.GetOrStore<String>("CacheKey",() => "Foo", 900)

Nó dường như có một vấn đề với tham chiếu đến phương pháp GetOrStore trên đối tượng Cache là một phương thức mở rộng.

Mã biên dịch nhưng thử nghiệm không thành công với ngoại lệ này.

Tôi cần phải làm gì để thiết lập kết quả của một phương pháp tiện ích mở rộng như thế này?

+2

Bạn đã thử phương pháp/thuộc tính được sử dụng trong phương pháp mở rộng chưa? –

+0

Phương thức mở rộng là một phương thức tĩnh trong một lớp tĩnh. Tôi không mong đợi 'GetOrStore' để thực sự được gọi và do đó mocking ra các phương pháp nó gọi là không cần thiết, phải không? –

+0

'GetOrStore' gọi' Get' và 'Insert' trên đối tượng' Cache'. Phương thức 'GetOrStore' không thực sự được thực thi mặc dù nó là một mô hình ... –

Trả lời

19

Phương pháp mở rộng không thể được mô phỏng như các phương pháp mẫu vì chúng không được xác định trên loại giả mạo của bạn. Chúng được định nghĩa trong các lớp tĩnh khác. Vì bạn không thể chỉ đơn giản là giả lập chúng, thay vào đó bạn nên thử tất cả các phương thức/thuộc tính được sử dụng bởi phương thức mở rộng.

Đây là ví dụ về cách các phương thức tiện ích mở rộng kết hợp chặt chẽ mã của bạn với các lớp khác. Dù bạn làm gì, lớp học của bạn phụ thuộc vào những phương pháp tĩnh đó. Bạn không thể thử nó và kiểm tra nó trong sự cô lập. Tôi đề nghị tái cấu trúc mã của bạn để di chuyển các phương thức đó sang các lớp của riêng chúng nếu có bất kỳ logic nào bên trong.

+1

Cảm ơn sự giúp đỡ của bạn. Tôi quyết định mương phương pháp mở rộng và đặt ICache của riêng mình là sugested. Mọi thứ trông đơn giản hơn nhiều bây giờ. –

5

Moq không thể giả lập phương pháp tĩnh, do đó bạn sẽ không thể giả lập tiện ích mở rộng GetOrStore của mình.

Thay vào đó, chỉ cần thử các phương thức GetInsert của đối tượng Cache.

+0

Cảm ơn @FlorianGreinacher. Vấn đề duy nhất với điều này là tôi không thể thiết lập 'Get' vì nó không phải là ảo. –

0

Có thể, mặc dù không đẹp ... Tôi giả sử có một số đối tượng bộ nhớ cache nội bộ bên trong phương pháp mở rộng của bạn hoặc tham chiếu đến một số bộ nhớ cache ở đâu đó. Bạn có thể sử dụng sự phản chiếu để thay thế đối tượng bên trong để lưu trữ bộ nhớ cache. Bạn nhận được một cái gì đó như thế này bên trong thử nghiệm của bạn:

IFixture fixture = new Fixture().Customize(new AutoMoqCustomization()); 

Mock<ICache> internalCache = new Mock<ICache>(); 
internalCache.Setup(i => i.Get<String>("CacheKey")).Returns("Foo"); 

var cacheExtension = typeof(CacheExtensions); 
var inst = cacheExtension.GetField("_internalCache", BindingFlags.NonPublic | BindingFlags.Static); 
inst.SetValue(cacheExtension, internalCache.Object); 

Lưu ý rằng mã này không được kiểm tra, nhưng cần giải thích ý tưởng cơ bản.

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