C#模拟混凝土类.如何



我想模拟一个具体的类别,是特定的分类。

上下文:

我有一个定义如下的位置模拟类别:

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(),我需要模拟具体类排序的Dictionary&lt;>。不幸的是,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中以这种样式编写单元测试?或者您不采用已知约束的路径?

您的帮助非常感谢。

另一种方法是使用单元测试工具,该工具允许您模拟混凝土类,例如我使用的是打字机隔离器,并且能够创建您要进行的测试:

[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));
}

您不应在这里模拟字典。实际上,这是LocationMapper类的实现细节。并且应该通过封装隐藏。您可能会使用其他任何内容来存储位置 - 数组,列表或简单词典。LocationMapper是否满足其要求都没关系。在这种情况下有什么要求?像

位置映射器应能够映射已添加到映射器的位置

目前,您的映射器非常毫无用处,它对字典行为没有任何添加。您缺少核心 - 映射。我只能假设该课程将如何使用。您需要一些公共接口才能映射。测试应该看起来像(此处使用的自动固定和fluentAssertions):

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

当该测试通过时,您可以将位置添加到映射器并使用映射器映射这些位置。

您有两个选项:如果使用VS Enterprise,请使用Microsoft假货为您的类生成垫片。(如果您想要样本,请给我)>

如果您不使用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)
}