2008-09-16 39 views
12

Tôi mới dùng RhinoMocks, và cố nắm bắt cú pháp ngoài những gì đang xảy ra dưới mui xe.RhinoMocks: Cách đúng để chế tài sản phẩm getter

Tôi có một đối tượng người dùng, chúng tôi sẽ gọi nó là Người dùng có tài sản có tên IsAdministrator. Giá trị cho IsAdministrator được đánh giá thông qua một lớp khác để kiểm tra các quyền bảo mật của người dùng và trả về true hoặc false dựa trên các quyền đó. Tôi đang cố gắng để giả mạo lớp người dùng này, và giả mạo giá trị trả về cho IsAdministrator để cô lập một số xét nghiệm đơn vị.

Đây là những gì tôi đang làm cho đến nay:

public void CreateSomethingIfUserHasAdminPermissions() 
{ 
    User user = _mocks.StrictMock<User>(); 
    SetupResult.For(user.IsAdministrator).Return(true); 

    // do something with my User object 
} 

Bây giờ, tôi đang mong đợi rằng Rhino sẽ 'giả' cuộc gọi đến getter tài sản, và chỉ trở thành sự thật đối với tôi. Điều này có đúng không? Hiện tại tôi đang nhận được một ngoại lệ vì phụ thuộc trong tài sản IsAdministrator.

Ai đó có thể giải thích cách tôi có thể đạt được mục tiêu của mình ở đây không?

Trả lời

11

Một lưu ý nhanh trước khi tôi chuyển sang điều này. Thông thường, bạn muốn tránh việc sử dụng một mô hình "nghiêm ngặt" vì nó làm cho một thử nghiệm giòn. Một mô hình nghiêm ngặt sẽ ném một ngoại lệ nếu bất cứ điều gì xảy ra mà bạn không nói rõ ràng với Rhino sẽ xảy ra. Ngoài ra tôi nghĩ bạn có thể hiểu lầm chính xác những gì Rhino đang làm khi bạn thực hiện một cuộc gọi để tạo ra một mô hình. Hãy suy nghĩ về nó như là một đối tượng tùy chỉnh có hoặc được bắt nguồn từ, hoặc thực hiện System.Type bạn đã xác định. Nếu bạn tự làm nó sẽ giống như sau:

public class FakeUserType: User 
{ 
    //overriding code here 
} 

Vì IsAdministrator có lẽ chỉ là thuộc tính công khai trên loại người dùng bạn không thể ghi đè lên loại kế thừa.

Theo như câu hỏi của bạn, có nhiều cách bạn có thể xử lý vấn đề này. Bạn có thể thực hiện IsAdministrator như một tài sản ảo trên lớp người sử dụng của bạn như aaronjensen đề cập như sau:

public class User 
{ 
    public virtual Boolean IsAdministrator { get; set; } 
} 

Đây là một cách tiếp cận ok, nhưng chỉ khi bạn có kế hoạch kế thừa từ lớp tài khoản của bạn. Ngoài ra nếu bạn không giả mạo các thành viên khác trong lớp này, họ cũng sẽ phải là ảo, đó có lẽ không phải là hành vi mong muốn.

Một cách khác để thực hiện điều này là thông qua việc sử dụng giao diện. Nếu nó thực sự là lớp người dùng bạn muốn Mock thì tôi sẽ trích xuất một giao diện từ nó. Ví dụ trên của bạn sẽ trông giống như sau:

public interface IUser 
{ 
    Boolean IsAdministrator { get; } 
} 

public class User : IUser 
{ 
    private UserSecurity _userSecurity = new UserSecurity(); 

    public Boolean IsAdministrator 
    { 
     get { return _userSecurity.HasAccess("AdminPermissions"); } 
    } 
} 

public void CreateSomethingIfUserHasAdminPermissions() 
{ 
    IUser user = _mocks.StrictMock<IUser>(); 
    SetupResult.For(user.IsAdministrator).Return(true); 

    // do something with my User object 
} 

Bạn có thể trở nên giàu có hơn nếu bạn muốn sử dụng dependency injection and IOC nhưng nguyên tắc cơ bản là giống nhau trên bảng. Thông thường, bạn muốn các lớp của bạn phụ thuộc vào các giao diện hơn là triển khai cụ thể.

Tôi hy vọng điều này sẽ hữu ích. Tôi đã sử dụng RhinoMocks trong một thời gian dài trên một dự án lớn bây giờ vì vậy đừng ngần ngại hỏi tôi những câu hỏi về TDD và chế nhạo.

+1

Chỉ cần lưu ý rằng ví dụ cuối cùng cần một '_mocks.ReplayAll()' trước khi bạn làm bất cứ điều gì với phần sơ khai IUser. –

1

Đảm bảo IsAdministrator là ảo.

Ngoài ra, hãy chắc chắn bạn gọi _mocks.ReplayAll()

0

_mocks.ReplayAll() sẽ không làm gì cả. Nó chỉ là vì bạn sử dụng SetupResult.For() mà không tính. Sử dụng Expect.Call() để chắc chắn rằng mã của bạn làm mọi thứ chính xác.

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