RhinoMocks: правильный способ издевательства над объектом - PullRequest
12 голосов
/ 17 сентября 2008

Я новичок в RhinoMocks и пытаюсь понять синтаксис в дополнение к тому, что происходит под капотом.

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

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

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

    // do something with my User object
} 

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

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

Ответы [ 3 ]

11 голосов
/ 17 сентября 2008

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

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

Поскольку IsAdministrator, вероятно, является просто открытым свойством для типа User, его нельзя переопределить в типе наследования.

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

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

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

Еще один способ сделать это - использовать интерфейсы. Если это действительно класс 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
}

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

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

1 голос
/ 17 сентября 2008

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

Кроме того, обязательно вызовите _mocks.ReplayAll ()

0 голосов
/ 08 апреля 2010

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

...