2010-03-29 40 views
14

Tôi có chức năng tôi muốn Moq. Vấn đề là phải mất 5 tham số. Khuôn khổ chỉ chứa Action<T1,T2,T3,T4> và Moq's chung CallBack() chỉ quá tải Hành động và bốn phiên bản chung. Có cách giải quyết thanh lịch cho việc này không?Moq một chức năng với hơn 5 tham số và truy cập đối số lời gọi

Đây là những gì tôi muốn làm:

public class Filter : IFilter 
{ 
    public int Filter(int i1, int i2, int i3, int i4, int i5){return 0;} 
} 

//Moq code: 
var mocker = new Mock<IFilter>(); 
mocker.Setup(x => x.Filter( 
    It.IsAny<int>(), 
    It.IsAny<int>(), 
    It.IsAny<int>(), 
    It.IsAny<int>(), 
    It.IsAny<int>(), 
    It.IsAny<int>()) 
.Callback 
( 
    (int i1, int i2, int i3, int i4, int i5) => i1 * 2 
); 

Moq không cho phép điều này vì không có hành động chung chung mà phải mất 5 + thông số. Tôi đã sử dụng cái cuống riêng của mình. Rõ ràng, nó sẽ là tốt hơn để sử dụng Moq với tất cả các xác minh của nó, vv

+0

Có thể sẽ không giúp bạn, nhưng trong .NET 4.0 Action có thể mất đến 16 tham số! – RichardOD

+1

Ngay cả khi bạn ở trong .NET 4.0, Moq vẫn chỉ hỗ trợ tối đa 4 tham số trong phiên bản beta mới nhất của nó. Để khắc phục nó, bạn sẽ phải tải xuống nguồn và cuộn mã nguồn của riêng mình. –

+1

Bạn có thể sử dụng phương pháp mở rộng – Thomas

Trả lời

3

Tôi biết điều này có thể phá vỡ thiết kế của bạn, nhưng với nhiều thông số sẽ không tốt hơn để vượt qua một mảng param?

+0

+1, mặc dù đối số tham số có thể tốt hơn nếu đối số đại diện cho các khái niệm khác nhau –

+0

Như bạn đã đề cập trong phản hồi tiếp theo của mình, tôi cần thay đổi Moq vì nó không cho phép quá tải này . Bất kể, tôi cần generics vì vậy tôi có thể truy cập các tham số invocation. – beerncircus

+1

Thực ra, như Mark đã chỉ ra, một giải pháp tốt hơn là truyền một đối tượng chứa tất cả các tham số bạn cần. Tất nhiên, điều đó sẽ thay đổi cách bạn giả lập nó. –

-1

Điều này thực sự khá đơn giản. Chỉ cần xác định Action<T1, T2, T3, T4, T5> của riêng bạn và bạn tốt để đi.

public delegate void Action<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5); 

Đây là tất cả những gì Action, Action<T> ..., Action<T1, T2, T3, T4> được định nghĩa như trong khuôn khổ. Chỉ có bấy nhiêu thôi. Đơn giản!

+3

Bạn sẽ vẫn phải sửa đổi mã nguồn Moq để hỗ trợ nhiều hơn bốn tham số trong một cuộc gọi lại. –

+0

@ "Robert Harvey" - Vâng, bạn nói đúng. Tôi đã bỏ qua điều đó. Có lẽ Currying có thể được sử dụng? – Enigmativity

+0

Thay đổi quá tải Moq để thực hiện Hành động của hơn 5 thông số là giải pháp duy nhất tôi thấy. Bạn có ý nghĩa gì khi "cà ri"? – beerncircus

3

Sử dụng một phương pháp mở rộng để mở rộng khung moq nếu bạn không muốn sửa đổi nguồn.

//Extension Method 

    public static class MoqExtensions 
    { 
     public static void Callback<T1, T2, T3, T4, T5>(this ICallback iCallBack, Action<T1, T2, T3, T4, T5> action) 
     { 
     } 
    } 

//Your class and interface 

     public interface IMyClass 
     { 
      void Method(string arg1, string arg2, string arg3, string arg4, string arg5); 
     } 

     public class MyClass : IMyClass 
     { 
      public void Method(string arg1, string arg2, string arg3, string arg4, string arg5) 
      { 
       //Do something 
      } 
     } 

//Your test 

     [TestMethod] 
     public void ExampleTest() 
     { 
      Mock<IMyClass> mockMyClass = new Mock<IMyClass>(); 
      mockMyClass.Setup(s => s.Method(It.IsAny<string>(), 
              It.IsAny<string>(), 
              It.IsAny<string>(), 
              It.IsAny<string>(), 
              It.IsAny<string>())) 
       .Callback<string, string, string, string, string>((string arg1, string arg2, string arg3, string arg4, string arg5) 
        => { /* Run your mock here */ }); 
     } 
+0

Vậy thì sao?Tôi vẫn cần phải viết phương pháp của riêng mình, mà không phải là bất kỳ dễ dàng hơn so với sửa đổi mã nguồn. – beerncircus

+0

Tôi đã cập nhật ví dụ về mã của mình để đưa ra một ví dụ đơn giản. Tất cả những gì bạn đang làm là mở rộng giao diện ICallback là một phần của khung công tác moq. Bạn có quen thuộc với việc tạo các phương thức mở rộng không? – Thomas

+1

Phương pháp mở rộng của bạn không thực sự làm bất cứ điều gì, vì vậy làm thế nào nó sẽ làm việc, ngoài việc không làm cho trình biên dịch phàn nàn? –

16

Điều này được hỗ trợ trong bản phát hành cuối cùng của Moq 4.0 (4.0.10827), được phát hành vào ngày 12 tháng 4 năm 2011. Nếu bạn đang sử dụng .NET 4, bạn sẽ có thể giả lập 16 thông số.

+1

Đây là câu trả lời hay nhất ... –

4

Tôi biết đây là một bài đăng cũ, nhưng tôi nghĩ mã này có thể giúp những người khác gặp vấn đề này với phiên bản cũ hơn của Moq. Dưới đây là một ví dụ với 5 và 6 đối số, và nó có thể được mở rộng để hỗ trợ bất kỳ số nào.

Tôi đã thử nghiệm phiên bản này với phiên bản 3.1.0.0, nhưng cũng nên hoạt động với các phiên bản khác.

Bí quyết là sử dụng phản ánh để truy cập 'SetCallbackWithArguments' phương pháp bảo vệ trên lớp cơ bản ...

Hy vọng điều này là sử dụng cho một người nào đó!

public delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); 
public delegate void Action<T1, T2, T3, T4, T5, T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); 

public static class MoqExtensions 
{ 
    public static ICallbackResult Callback<T1, T2, T3, T4, T5>(this ICallback call, Action<T1, T2, T3, T4, T5> callback) 
    { 
     call.SetCallbackWithArguments(callback); 
     return (ICallbackResult)call; 
    } 

    public static ICallbackResult Callback<T1, T2, T3, T4, T5, T6>(this ICallback call, Action<T1, T2, T3, T4, T5, T6> callback) 
    { 
     call.SetCallbackWithArguments(callback); 
     return (ICallbackResult)call; 
    } 

    public static void SetCallbackWithArguments(this ICallback call, Delegate callback) 
    { 
     MethodInfo methodInfo = call.GetType().GetMethod("SetCallbackWithArguments", BindingFlags.NonPublic | BindingFlags.Instance); 
     methodInfo.Invoke(call, new object[] { callback }); 
    } 
} 
Các vấn đề liên quan