2009-02-12 29 views
21

Tôi đang viết một giao diện dòng lệnh cho dự án của mình. Người dùng nhập "tạo dự án foo" và tìm thấy trình điều khiển chịu trách nhiệm về "dự án" và sau đó gọi phương thức Create, chuyển "foo" làm đối số đầu tiên.Tôi có thể yêu cầu Moq thêm thuộc tính vào lớp giả không?

Nó chủ yếu dựa vào các thuộc tính và phản ánh: bộ điều khiển trông giống như sau:

[ControllerFor("project")] 
class ProjectController 
{ 
    [ControllerAction("create")] 
    public object Create(string projectName) { /* ... */ } 
} 

Tôi muốn sử dụng Moq trong các bài kiểm tra đơn vị cho các phân tích cú pháp, một cái gì đó như thế này:

Mock<IProjectsController> controller = new Mock<IProjectsController>(); 
controller.Expect(f => f.Create("foo")); 

parser.Register(controller.Object); 
parser.Execute("create project foo"); 

controller.VerifyAll(); 

Việc thêm thuộc tính vào giao diện dường như không hoạt động - chúng không được kế thừa bởi các lớp dẫn xuất.

Tôi có thể yêu cầu Moq thêm thuộc tính vào lớp đang được mô phỏng không?

Trả lời

31

Cập nhật: Tôi vừa mới nhận ra rằng bạn thực sự có thể thêm các thuộc tính với một loại hiện tại bằng cách sử dụng TypeDescriptor.AddAttributes, có thể được thực hiện đối với một trường hợp hoặc aa loại:

Mock<IRepository> repositoryMock = new Mock<IRepository>(); 

CustomAttribute attribute = new CustomAttribute(); 

// option #1: to the instance 
TypeDescriptor.AddAttributes(repositoryMock.Object, attribute); 

// option #2: to the generated type 
TypeDescriptor.AddAttributes(repositoryMock.Object.GetType(), attributes); 

Nếu bạn cần, AddAttribute trả về một TypeDescriptorProvider có thể được chuyển đến TypeDescriptor.RemoveProvider để loại bỏ các thuộc tính sau đó.

Lưu ý rằng Attribute.GetCustomAttributes sẽ không tìm thấy thuộc tính được thêm vào lúc chạy theo cách này. Thay vào đó, hãy sử dụng TypeDescriptor.GetAttributes.

gốc trả lời

tôi không belive Moq (hoặc bất kỳ khuôn khổ chế giễu khác cho rằng vấn đề) hỗ trợ các thuộc tính tùy chỉnh. Tôi biết rằng Castle Proxy (khuôn khổ thường được sử dụng để thực sự tạo ra các lớp học) hiện hỗ trợ nó, nhưng không có cách nào để truy cập nó thông qua Moq.

Đặt cược tốt nhất của bạn là trừu tượng phương pháp tải Thuộc tính vào giao diện (chấp nhận loại và loại thuộc tính) và sau đó giả lập điều đó.

Edit: Ví dụ:

public interface IAttributeStrategy 
{ 
    Attribute[] GetAttributes(Type owner, Type attributeType, bool inherit); 
    Attribute[] GetAttributes(Type owner, bool inherit); 
} 

public class DefaultAttributeStrategy : IAttributeStrategy 
{ 
    public Attribute[] GetAttributes(Type owner, Type attributeType, bool inherit) 
    { 
     return owner.GetCustomAttributes(attributeType, inherit); 
    } 

    public Attribute[] GetAttributes(Type owner, bool inherit) 
    { 
     return owner.GetCustomAttributes(inherit); 
    } 
} 

Lớp mà cần các thuộc tính sử dụng một thể hiện của IAttributeStrategy (hoặc thông qua một container IoC, hoặc có nó tùy chuyển vào constructor). Thông thường nó sẽ là một DefaultAttributeStrategy, nhưng bây giờ bạn có thể giả định IAttributeStrategy để ghi đè đầu ra.

Nó có thể âm thanh phức tạp, nhưng thêm một lớp trừu tượng là dễ dàng hơn nhiều so với cố gắng để thực sự mô phỏng thuộc tính.

+0

Bạn có thể mở rộng trên phương pháp tiếp cận giao diện không? Tôi không nghĩ rằng nó sẽ phù hợp với những gì tôi đang làm, nhưng tôi muốn thấy nó chắc chắn. –

+0

Xem câu trả lời cập nhật của tôi về TypeDescriptor.AddAttributes –

+0

(cho tôi biết nếu câu trả lời cập nhật của tôi giải quyết được vấn đề của bạn và tôi sẽ xóa các phần cũ của câu trả lời) –

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