2012-02-16 78 views
1

我已試過以此作爲懲戒註冊表指南:http://www.rhyous.com/2011/11/04/unit-testing-registry-access-with-rhinomocks-and-systemwrapper/懲戒註冊表 - SystemWrapper

當我嘗試模擬它,我總是在我的課爲「REG」返回null它嘗試時要做OpenSubKey調用,在我的_Real()測試中工作正常。

測試:

private RegistryService CreateMockedRegistryService() 
{ 
    var registryService = new RegistryService(MockRepository.GenerateMock<ILoggerFacadeExtended>(), MockRepository.GenerateMock<IConnectivityService>()); 
    // Mock the Base Key so we can throw errors and manipulate it 
    registryService.ChangeBaseKey(MockRepository.GenerateMock<IRegistryKey>()); 
    return registryService; 
} 

private IRegistryKey CreateMockedHKLM() 
{ 
    IRegistryKey hklmMock = MockRepository.GenerateMock<IRegistryKey>(); 
    hklmMock.Stub(x => x.Name).Return("HKEY_LOCAL_MACHINE"); 
    return hklmMock; 
} 

[TestMethod()] 
public void GetRegistryKeyTest_Mocked() 
{ 
    IRegistryService target = CreateMockedRegistryService(); 
    string machineName = "localhost"; 
    RegistryHive hive = RegistryHive.LocalMachine; 
    string path = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion"; 
    string valueName = "SystemRoot"; 
    object defaultValue = @"C:\Windows"; 

    IRegistryKey keyMock = CreateMockedHKLM(); 
    keyMock.Stub(x => x.OpenRemoteBaseKey(hive, machineName)).Return(CreateMockedHKLM()); 
    var subKeyMock = MockRepository.GenerateMock<IRegistryKey>(); 
    subKeyMock.Stub(x => x.Name).Return(keyMock.Name + @"\" + path); 
    subKeyMock.Stub(x => x.GetValueNames()).Return(new string[] { valueName }); 
    subKeyMock.Stub(x => x.GetValue(valueName)).Return(defaultValue); 

    keyMock.Stub(x => x.OpenSubKey(path)).Return(subKeyMock); 
    keyMock.Stub(x => x.GetValue(valueName)).Return(defaultValue); 
    target.ChangeBaseKey(keyMock); 

    IResult<object> expected = new Result<object>() { Results = defaultValue }; 
    IResult<object> actual; 
    actual = target.GetRegistryKey(machineName, hive, path, valueName, defaultValue); 

    Assert.AreEqual(expected.Results, actual.Results); 
} 

[TestMethod()] 
public void GetRegistryKeyTest_Real() 
{ 
    IRegistryService target = CreateMockedRegistryService(); 
    string machineName = "localhost"; 
    RegistryHive hive = RegistryHive.LocalMachine; 
    string path = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion"; 
    string valueName = "SystemRoot"; 
    object defaultValue = @"C:\Windows"; 

    // We don't want to use the regular Mocked version but actually hit the registry so it works 
    IRegistryKey baseKey = new RegistryWrap().LocalMachine; 
    target.ChangeBaseKey(baseKey); 

    IResult<object> expected = new Result<object>() { Results = defaultValue }; 
    IResult<object> actual; 
    actual = target.GetRegistryKey(machineName, hive, path, valueName, defaultValue); 

    Assert.AreEqual(expected.Results, actual.Results); 
} 

實際類:

private IRegistryKey _BaseKey; 
public IRegistryKey BaseKey 
{ 
    get 
    { 
     if (_BaseKey == null) 
     { 
      _BaseKey = new RegistryWrap().LocalMachine; 
     } 
     return _BaseKey; 
    } 
} 

public void ChangeBaseKey(IRegistryKey inBaseKey) 
{ 
    _BaseKey = inBaseKey; 
} 

public IResult<object> GetRegistryKey(string machineName, RegistryHive hive, string path, string valueName, object defaultValue) 
    { 
     return GetRegistryKey(BaseKey.OpenRemoteBaseKey(hive, machineName), path, valueName, defaultValue); 
    } 
} 

public IResult<object> GetRegistryKey(IRegistryKey baseKey, string path, string valueName, object defaultValue) 
{ 
    IResult<object> result = new Result<object>(); 
    try 
    { 
     if (baseKey == null) throw new ArgumentNullException("baseKey"); 
     if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); 
     if (string.IsNullOrWhiteSpace(valueName)) throw new ArgumentException("valueName"); 
     var reg = baseKey.OpenSubKey(path); 
     result.Results = reg.GetValue(valueName); // reg is null when I try to Mock it 
    ..... 
    } 
} 

回答

0

我想通了,我將存根與OpenSubKey處理初始keyMock,而不是一個被OpenRemoteBaseKey()

返回

這裏是固定代碼:

[TestMethod()] 
public void GetRegistryKeyTest_Mocked() 
{ 
    IRegistryService target = CreateMockedRegistryService(); 
    string machineName = "localhost"; 
    RegistryHive hive = RegistryHive.LocalMachine; 
    string path = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion"; 
    string valueName = "SystemRoot"; 
    object defaultValue = @"C:\Windows"; 


    var keyMock = CreateMockedHKLM(); 
    var remoteKeyMock = CreateMockedHKLM(); 
    var subKeyMock = MockRepository.GenerateMock<IRegistryKey>(); 
    subKeyMock.Stub(x => x.Name).Return(keyMock.Name + @"\" + path); 
    subKeyMock.Stub(x => x.GetValueNames()).Return(new string[] { valueName }); 
    subKeyMock.Stub(x => x.GetValue(valueName)).Return(defaultValue); 
    remoteKeyMock.Stub(x => x.OpenSubKey(path)).Return(subKeyMock); 
    remoteKeyMock.Stub(x => x.GetValue(valueName)).Return(defaultValue); 

    keyMock.Stub(x => x.OpenRemoteBaseKey(hive, machineName)).Return(remoteKeyMock); 
    target.ChangeBaseKey(keyMock); 

    actual = target.GetRegistryKey(machineName, hive, path, valueName, defaultValue); 

    Assert.AreEqual(expected.Results, actual.Results); 
    subKeyMock.AssertWasCalled(x => x.GetValue(valueName)); 
} 
+0

好。現在問自己我在測試什麼?它看起來像你正在測試一個模擬,而不是任何可以使它生產的實現。你的測試名稱甚至反映了它!如果你想'模擬'RepositoryService,你會測試它是否像你期望的那樣對其他對象(mock)進行操作(例如它是否叫'OpenRemoteBasekey')。你現在大多數似乎是在對它進行存根測試,並測試存根是否返回你設定的返回值。 – Joppe 2012-02-17 00:19:03

+0

@Tungano你有更好的方式單元測試註冊表與實際上觸摸註冊表?它仍然貫穿我的課程代碼,並給我我正在尋找的結果......是不是Mocks和Stubs的重點?我一直試圖讓這個工作整天,所以請讓我知道,如果你有更好的方式來做到這一點:) – John 2012-02-17 00:45:36

+0

如果你想測試一些依賴RegistryService的代碼,並避免它觸及實際的註冊表:Stub GetRegistryKey方法。如果兩種方法都是虛擬的,則可以使用模擬框架來執行此操作。或者創建一個IRegistryService並使用你的模擬框架來創建一個存根。然後確保你可以得到測試代碼來使用你的存根(首選依賴注入)。 – Joppe 2012-02-17 00:52:56