Rhino Mocks - имитируйте вызов метода для службы внутри свойства

Я пытаюсь проверить, получает ли свойство свое значение в результате возврата вызова службы, но у меня возникают проблемы с издевательством над вызовом службы.

Вот моя собственность:

    public ICountry Country
    {
        get
        {
            if (_country == null)
            {
                ICountryService countryService = new CountryService();
                _country = countryService.GetCountryForCountryId(_address.CountryId);
            }
            return _country;
        }
    }

Вот моя попытка проверить это:

    [TestMethod]
    public void Country_should_return_Country_from_CountryService()
    {
        const string countryId = "US";
        _address.CountryId = countryId;

        var address = MockRepository.GenerateStub<Address>(_address);

        var country = MockRepository.GenerateMock<ICountry>();
        var countryService = MockRepository.GenerateStub<ICountryService>();

        countryService.Stub(x => x.GetCountryForCountryId(countryId)).IgnoreArguments().Return(country);

        Assert.AreEqual(address.Country, country);
    }

Я все время получаю сообщение об ошибке, потому что вызывается настоящая countryService, а не мой макет. Я использую MsTest и Rhino Mocks. Что я делаю неправильно?


person Martin    schedule 03.02.2011    source источник


Ответы (1)


Ваша проблема в том, что свойство напрямую строит зависимость. Из-за этого фиктивный сервис не вызывается, вызывается реальная реализация CountryService.

Обойти это можно, используя внедрение конструктора фабрики CountryService (или самой службы) в конструктор других объектов (Address?). Таким образом, вы можете вернуть свой поддельный CountryService (макет) и вызвать его методом

Например:

private ICountryService _countryService;

//constructor
public OuterObject(ICountryService countryService)
{
    //maybe guard clause
    _countryService = countryService;
}


public ICountry Country
{
    get
    {
        if (_country == null)
        {
            _country = _countryService.GetCountryForCountryId(_address.CountryId);
        }
        return _country;
    }
}

Затем вам нужно будет передать имитацию ICountryService в другой конструктор объектов в вашем модульном тесте.

person saret    schedule 03.02.2011
comment
Проблема в том, что я также вызываю государственную службу, чтобы получить свойство IState, и могут быть другие. Я не хотел полагаться на передачу этих объектов в класс только для того, чтобы получить объект. - person Martin; 03.02.2011
comment
Тогда вы могли бы использовать класс ObjectFactory, который позволит вам это сделать - objectFactory.GetInstance ‹ICountryService› () ИЛИ objectFactory.GetInstance ‹IStateService› () ... Таким образом, у вас есть только одна зависимость для внедрения в класс - внутренне ObjectFactory может использовать контейнер IOC или любой другой механизм, который вы хотите создать, при условии, что он позволяет вам заменять эти зависимости для ваших модульных тестов. - person saret; 03.02.2011