Не можете понять, почему этот Rhino Mock не работает?Ошибка: ожидаемая правда, но была: ложная - PullRequest
0 голосов
/ 10 сентября 2010

Вот код:

public interface IAccessPoint
{
    int BackHaulMaximum { get; set; }

    bool BackHaulMaximumReached();
    void EmailNetworkProvider();
}

public class AccessPoint : IAccessPoint
{

    public int BackHaulMaximum { get; set; }

    public bool BackHaulMaximumReached()
    {
        if (BackHaulMaximum > 80)
        {
            EmailNetworkProvider();
            return true;
        }
        return false;
        }

    public void EmailNetworkProvider()
    {

    }
}

//Test
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
        var apMock = MockRepository.GenerateMock<IAccessPoint>();

        apMock.Stub(x => x.BackHaulMaximum).Return(81);

        Assert.AreEqual(true, apMock.BackHaulMaximumReached());

        apMock.AssertWasCalled(x => x.EmailNetworkProvider());
 }

Ответы [ 3 ]

4 голосов
/ 10 сентября 2010

Вы не должны издеваться над классом, который вы тестируете. Вы должны только издеваться над классами, от которых зависит тестируемый класс. Примерно так:

public interface IAccessPoint
{
    int BackHaulMaximum { get; set; }

    bool BackHaulMaximumReached();
    void EmailNetworkProvider();
}

public class AccessPoint : IAccessPoint
{
    private IMailProvider Mailer { get; set; }

    public AccessPoint( IMailProvider provider )
    {
        this.Mailer = provider ?? new DefaultMailProvider();
    }

    public int BackHaulMaximum { get; set; }

    public bool BackHaulMaximumReached()
    {
        if (BackHaulMaximum > 80)
        {
            EmailNetworkProvider();
            return true;
        }
        return false;
        }

    public void EmailNetworkProvider()
    {
        this.Mailer.SendMail(...);
    }
}

[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()  
{  
    var mailerMock = MockRepository.GenerateMock<IMailProvider>();  

    mailerMock .Expect( m => m.SendMail( ... specify argument matches ... ) ); 

    var accessPoint = new AccessPoint( mailerMock ); 

    accessPoint.BackHaulMaximum = 81;

    Assert.IsTrue( accessPoint.BackHaulMaximumReached() );

    mailerMock.VerifyAllExpectations();
}
0 голосов
/ 10 сентября 2010

Я бы изменил код следующим образом:

    //Test
    [Test]
    public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
    {

        var mockRepo = new MockRepository();
        var apMock = mockRepo.PartialMock<AccessPoint>();

        using (mockRepo.Record())
        {
            Expect.Call(apMock.EmailNetworkProvider).Repeat.Once();
        }
        using (mockRepo.Playback())
        {
            apMock.BackHaulMaximum = 81;
            Assert.AreEqual(true, apMock.BackHaulMaximumReached());
        }
        mockRepo.VerifyAll();
    }

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

Решением является PartialMock. Это позволяет применять поведение насмешки только к тем членам класса, который вы указали. Вы можете использовать его в нескольких синтаксисах, но самый безопасный и надежный метод - записывать и воспроизводить ожидания, а не вызывать метод Expected () для самого макета.

Мы используем его здесь для ожидания вызова нашего метода, который мы хотим смоделировать; ожидание вызова приведет к тому, что фактический метод не будет вызван. Затем выполняется класс, и используется логика фактического класса (отсюда и утверждение в нашем тесте успешно), но когда достигается вызов нашего ожидаемого метода, то, что на самом деле вызывается, - это фиктивный метод, обновляющий некоторые внутренние счетчики , Затем VerifyAll () подтверждает, что все ожидания произошли в соответствии с заданными настройками.

0 голосов
/ 10 сентября 2010

Я согласен с ответом tvanfosson.В 99% (возможно, в 100%) случаев вы не захотите издеваться над своим SUT.

Однако причина его сбоя заключается в том, что ваш звонок:

Assert.AreEqual(true, apMock.BackHaulMaximumReached()); 

is не приведет к фактическому вызову метода BackHaulMaximumReached ()!Он будет вызывать метод макета.

Редактировать

Если неясно, это означает, что BackHaulMaximumReached () вернет (я думаю) значение по умолчанию дляего тип возврата, который является «ложным» в случае bools.Таким образом, вам нужно заглушить этот метод, чтобы он возвращал true, чтобы передать Assert.AreEqual (как я уже сказал, это не очень хороший тест).

Ваше следующее утверждение не будет выполнено, поскольку EmailNetworkProvider () будетникогда не вызываться (опять же, потому что вы вызываете методы макета, а не методы реального SUT).

...