2008-09-16 3 views
12

Я новичок в RhinoMocks и пытаюсь понять синтаксис в дополнение к тому, что происходит под капотом.RhinoMocks: Правильный способ издеваться над имуществом getter

У меня есть объект пользователя, мы будем называть его User, у которого есть свойство IsAdministrator. Значение для IsAdministrator оценивается через другой класс, который проверяет права доступа пользователя и возвращает либо true, либо false на основе этих разрешений. Я пытаюсь высмеять этот класс пользователя и подделку возвращаемого значения для IsAdministrator, чтобы изолировать некоторые тесты Unit.

Это то, что я делал до сих пор:

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

    // do something with my User object 
} 

Теперь, я ожидаю, что Rhino собирается на «фальшивый» вызов недвижимости добытчика, и просто вернуть мне верен. Это неверно? В настоящее время я получаю исключение из-за зависимостей в свойстве IsAdministrator.

Может кто-нибудь объяснить, как я могу достичь своей цели здесь?

ответ

11

Одно быстрое примечание, прежде чем я прыгнуть в это. Как правило, вы хотите избежать использования «Строгого» макета, потому что это делает хрупкий тест. Строгий макет будет генерировать исключение, если что-то случится, что вы явно не сообщите, что Rhino произойдет. Также я думаю, что вы можете неправильно понимать, что делает Rhino, когда вы делаете звонок, чтобы создать макет. Подумайте об этом как о пользовательском объекте, который был либо получен, либо реализует определенный вами System.Type. Если вы сделали это сами, это будет выглядеть так:

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

С IsAdministrator, вероятно, просто общественная собственность на тип пользователя вы не можете изменить его в тип наследуемым.

Что касается вашего вопроса, есть несколько способов справиться с этим. Вы могли бы реализовать IsAdministrator в качестве виртуальной собственности на вашем пользовательском классе, как aaronjensen упоминается следующим образом:

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

Это нормально подход, но только если вы планируете наследовать от вашего класса User. Кроме того, если вы не подделываете других участников этого класса, они также должны быть виртуальными, что, вероятно, не является желаемым поведением.

Другой способ добиться этого - использование интерфейсов. Если это действительно класс пользователя, который вы хотите выполнить Mock, я бы извлек из него интерфейс. Ваш приведенный выше пример будет выглядеть примерно так:

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 
} 

Вы можете получить новые идеи, если вы хотите с помощью dependency injection and IOC но основной принцип остается тем же по всем направлениям. Как правило, вы хотите, чтобы ваши классы зависели от интерфейсов, а не от конкретных реализаций.

Надеюсь, это поможет. Я давно использую RhinoMocks в крупном проекте, поэтому не стесняйтесь задавать мне вопросы о TDD и насмехаться.

+1

Просто обратите внимание, что этот последний пример требует `_mocks.ReplayAll()` прежде чем вы что-нибудь сделаете с заглушкой IUser. – 2009-10-30 00:07:11

1

Убедитесь, что IsAdministrator является виртуальным.

Кроме того, убедитесь, что вы звоните _mocks.ReplayAll()

0

_mocks.ReplayAll() ничего не сделает. Это просто потому, что вы используете SetupResult.For(), который не учитывается. Используйте Expect.Call(), чтобы убедиться, что ваш код делает все правильно.