簡體   English   中英

C#模擬具體類。 怎么樣?

[英]C# Mock concrete class. How?

我想模擬一個具體的類,具體來說就是SortedDictionary。

內容:

我有一個LocationMapper類,定義如下:

public class LocationMapper
{
  private SortedDictionary<string, Location>() locationMap;
  public LocationMapper()
  {
    this.locationMap = new SortedDictionary<string, Location>();
  }

  public LocationMapper(SortedDictionary<string, Location> locations)
  {
    this.locationMap = locations;
  }

  public Location AddLocation(Location location)
  {
    if(! locationMap.ContainsKey(location.Name))
    {
      locationMap.Add(location.Name, location)
    }
    return locationMap[location.Name];
  }  
}

要對AddLocation()進行單元測試,我需要模擬具體的類SortedDictionary <>。 不幸的是,NSubstitute不允許這樣做。

The unit test that I had envisioned to write is below
[Test]
public void AddLocation_ShouldNotAddLocationAgainWhenAlreadyPresent()
{
  var mockLocationMap = ;//TODO
  //Stub mockLocationMap.ContainsKey(Any<String>) to return "true"
  locationMapper = new LocationMapper(mockLocationMap);
  locationMapper.AddLocation(new Location("a"));
  //Verify that mockLocationMap.Add(..) is not called
}

您將如何在DotNet中以這種風格編寫單元測試? 還是您不采用已知約束的方法?

非常感謝您的幫助。

您不應該在這里嘲笑字典。 實際上,這是LocationMapper類的實現細節。 並且應該通過封裝將其隱藏。 您可能會使用其他任何東西來存儲位置-數組,列表或簡單字典。 LocationMapper滿足要求並不重要。 在這種情況下有什么要求? 就像是

位置映射器應該能夠映射已添加到映射器的位置

當前,您的映射器幾乎沒有用,它對字典行為沒有任何幫助。 您缺少核心映射 我只能假設如何使用此類。 您需要一些公共接口進行映射。 測試應該看起來像(此處使用的AutoFixture和FluentAssertions):

var mapper = new LocationMapper();
var location = fixture.Create<Location>();
mapper.AddLocation(location);
mapper.Map(location.Name).Should().Be(location);

通過此測試后,您可以將位置添加到mapper並使用mapper映射這些位置。

另一種方法是使用一個單元測試工具,該工具允許您模擬具體的類,例如,我正在使用Typemock Isolator並能夠創建您要進行的測試:

[TestMethod]
public void TestMethod1()
{
    var fakeLocationMap = Isolate.Fake.Instance<SortedDictionary<string, Location>>();

    Isolate.WhenCalled(() => fakeLocationMap.ContainsKey(string.Empty)).WillReturn(true);

    var instance = new LocationMapper(fakeLocationMap);
    var res = instance.AddLocation(new Location("a"));

    Isolate.Verify.WasNotCalled(() => fakeLocationMap.Add(string.Empty, null));
}

您有兩種選擇:如果使用VS Enterprise,請使用Microsoft Fakes為您的班級生成Shim。 (如果需要樣品,請ping我)>

如果您不使用VS Enterprise(因為這里的大多數人),您將不得不反思:

[Test]
public void AddLocation_ShouldNotAddLocationAgainWhenAlreadyPresent()
{
  var locationMapper = new LocationMapper(mockLocationMap);
  locationMapper.AddLocation(new Location("a"));
  var dict = ((SortedDictionary<string, Location>)typeof(LocationMapper).GetField("locationMap", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(locationMapper));
  Assert.AreEqual("a", dict.FirstOrDefault().Name)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM