C#模拟混凝土类。怎么用?
我想模拟一个具体的类,具体来说是SortedDictionary 上下文: 我有一个LocationMapper类,定义如下:C#模拟混凝土类。怎么用?,c#,unit-testing,mocking,tdd,C#,Unit Testing,Mocking,Tdd,我想模拟一个具体的类,具体来说是SortedDictionary 上下文: 我有一个LocationMapper类,定义如下: public class LocationMapper { private SortedDictionary<string, Location>() locationMap; public LocationMapper() { this.locationMap = new SortedDictionary<string, Locat
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];
}
}
公共类位置映射器
{
私有SortedDictionary()locationMap;
公共位置映射器()
{
this.locationMap=new SortedDictionary();
}
公共位置映射器(分类词典位置)
{
this.locationMap=位置;
}
公共位置AddLocation(位置)
{
如果(!locationMap.ContainsKey(location.Name))
{
locationMap.Add(location.Name,location)
}
返回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
}
下面是我设想编写的单元测试
[测试]
public void AddLocation_不应在HenalReadyPresent()中添加位置
{
var mockLocationMap=;//TODO
//存根mockLocationMap.ContainsKey(任意)返回“true”
locationMapper=新的locationMapper(mockLocationMap);
locationMapper.AddLocation(新位置(“a”));
//验证是否未调用mockLocationMap.Add(..)
}
您将如何在DotNet中以这种风格编写单元测试?或者,对于已知的约束,您不采用此路径?
非常感谢您的帮助。您不应该在这里模仿字典。实际上,它是
LocationMapper
类的一个实现细节。它应该通过封装来隐藏。您可以使用其他任何东西来存储位置—数组、列表或简单字典。无论LocationMapper
是否满足其要求。这种情况下的要求是什么?差不多
位置映射器应该能够映射添加到映射器中的位置
目前,你的映射器是非常无用的,它不会增加任何字典行为。你错过了核心映射。我只能假设这个类将如何使用。您需要一些用于映射的公共接口。测试应如下所示(此处使用的自动夹具和流体组件):
var mapper=newlocationmapper();
var location=fixture.Create();
mapper.AddLocation(位置);
mapper.Map(location.Name).Should().Be(location);
当此测试通过时,您可以向mapper添加位置,并使用mapper映射这些位置。您不应该在此处模拟字典。实际上,它是
LocationMapper
类的一个实现细节。它应该通过封装来隐藏。您可以使用其他任何东西来存储位置—数组、列表或简单字典。无论LocationMapper
是否满足其要求。这种情况下的要求是什么?差不多
位置映射器应该能够映射添加到映射器中的位置
目前,你的映射器是非常无用的,它不会增加任何字典行为。你错过了核心映射。我只能假设这个类将如何使用。您需要一些用于映射的公共接口。测试应如下所示(此处使用的自动夹具和流体组件):
var mapper=newlocationmapper();
var location=fixture.Create();
mapper.AddLocation(位置);
mapper.Map(location.Name).Should().Be(location);
当此测试通过时,您可以向mapper添加位置并使用mapper映射这些位置。您有两个选项:如果您使用VS Enterprise,请使用Microsoft Fakes为您的类生成垫片。(如果您想要样品,请点击我)> 如果您不使用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)
}
[测试]
public void AddLocation_不应在HenalReadyPresent()中添加位置
{
var locationMapper=新的locationMapper(mockLocationMap);
locationMapper.AddLocation(新位置(“a”));
var dict=((SortedDictionary)typeof(LocationMapper).GetField(“locationMap”,BindingFlags.Instance | BindingFlags.NonPublic).GetValue(LocationMapper));
Assert.AreEqual(“a”,dict.FirstOrDefault().Name)
}
您有两种选择:如果您使用VS Enterprise,请使用Microsoft Fakes为您的类生成一个垫片。(如果您想要样品,请点击我)>
如果您不使用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)
}
[测试]
public void AddLocation_不应在HenalReadyPresent()中添加位置
{
var locationMapper=新的locationMapper(mockLocationMap);
locationMapper.AddLocation(新位置(“a”));
var dict=((SortedDictionary)typeof(LocationMapper).GetField(“locationMap”,BindingFlags.Instance | BindingFlags.NonPublic).GetValue(LocationMapper));
Assert.AreEqual(“a”,dict.FirstOrDefault().Name)
}
另一种方法是使用单元测试工具,该工具允许您模拟具体类,例如,我使用的是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));
}
[TestMethod]
公共void TestMethod1()
{
var fakeLocationMap=Isolate.false.Instance();
Isolate.WhenCalled(()=>fakeLocationMap.ContainsKey(string.Empty)).WillReturn(true);
var实例=新位置映射器(fakeLocationMap);
var res=instance.AddLocation(新位置(“a”));
隔离.Verify.WasNotCalled(()=>fakeLocationMap.Add(string.Empty,null));
}
另一种方法是使用单元测试工具,该工具允许您模拟具体类,例如,我使用的是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));
}
[TestMethod]
公共void TestMethod1()
{
var fakeLocationMap=Isolate.false.Instance();
Isolate.WhenCalled(()=>fakeLocationMap.ContainsKey(string.Empty)).WillReturn(true);
var实例=新位置映射器(fakeLocationMap);
var res=instance.AddLocation(新位置(“a”));
隔离.Verify.WasNotCalled(()=>fakeLocationMap.Add(string.Empty,null));
}
为什么要嘲笑它?为什么不创建一个实例并传入呢?您可以完全控制如何填充它