Rhino Mocks - 在属性中模拟对Service的方法调用

Mar*_*tin 1 unit-testing rhino-mocks

我试图测试该属性从Service调用的返回获得它的值,但我在模拟服务调用时遇到问题.

这是我的财产:

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

这是我尝试测试这个:

    [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);
    }
Run Code Online (Sandbox Code Playgroud)

我一直收到错误,因为正在调用真正的countryService,而不是我的模拟.我正在使用MsTest和Rhino Mocks.我究竟做错了什么?

sar*_*ret 6

您的问题是该属性是直接构造依赖项.由于这个原因,模拟服务没有被调用,实际真正的CountryService实现被调用.

解决这个问题的方法可能是在其他对象(Address?)构造函数中使用CountryService工厂(或服务本身)的构造函数注入.通过这种方式,您可以返回假的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要将模拟的ICountryService传递给单元测试中的其他对象构造函数

  • 你可以做的是利用一个可以让你做的ObjectFactory类 - objectFactory.GetInstance <ICountryService>()或者objectFactory.GetInstance <IStateService>()......这样你只有一个依赖注入类 - 内部ObjectFactory可以利用IOC容器或您想要构建它的对象的任何机制,只要它允许您为单元测试交换这些依赖项 (2认同)