2017-03-08 3 views
1

구체적인 SortedDictionary가되도록 구체적인 클래스를 모의하고 싶습니다.C# 모의 콘크리트 클래스. 방법?

상황 :

내가 다음과 같이 정의 LocationMapper 클래스가 : 단위 테스트 AddLocation에

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 <> 콘크리트 클래스를 모의 할 필요가있다. 불행히도 NS substitute는 그것을 허용하지 않습니다.

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에서이 스타일로 단위 테스트를 작성 가겠어요

? 또는 알려진 제약 조건에 대해이 경로를 사용하지 않습니까?

귀하의 도움에 감사드립니다.

+3

이 왜 조롱 : 예를 들어 내가 Typemock 아이솔레이터를 사용하고 당신이 만들고 싶어 테스트를 만들 수 있었다 함께 해요, 당신이 구체적인 클래스를 조롱 할 수있는 단위 테스트 도구? 왜 인스턴스를 만들고 전달하지 않는가? 당신은 당신이 그 결과를 주장 할 수 있다고 생각할 수 있기를 바라지 만 그것을 채울 수있는 완전한 통제력을 가지고 있습니다. 그것이 인터페이스 였고 확실한 모의지만, 구체적인 사전이 있다면, 나는 그것이 필요하다는 것을 보지 못합니다. – TyCobb

+0

당신은 실제로 무엇을 테스트하고 있습니까? 그것은 나에게 SortedDictionary가 보장하는 것을 수행하는지 실제로 테스트하고있는 것으로 보입니다. 달성하고자하는 가치는 무엇입니까? –

+0

@TyCobb, 필자는 단위 테스트 바이어스/선호도를 사용자의 열독을위한 템플릿 단위 테스트 케이스로 업데이트했습니다. – karthiks

답변

2

또 다른 방법은 사용하는 것입니다 : 당신이 (여기에 대다수의 사람들로) VS 엔터프라이즈를 사용하지 않는 경우에 당신은 반사에 의존해야 할 것이다>

을 (당신이 샘플을 원하는 경우에 저를 ping)

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

사전을 모방하면 안됩니다. 실제로 이것은 LocationMapper 클래스의 구현 세부 사항입니다. 캡슐화를 통해 숨겨져 있어야합니다. 배열, 목록 또는 간단한 사전과 같은 위치를 저장하는 데는 다른 것을 사용할 수 있습니다. LocationMapper이 요구 사항을 충족하는지는 중요하지 않습니다. 이 경우 요구 사항은 무엇입니까?

위치 매퍼 같은 뭔가가 현재 당신의 매퍼 꽤 쓸모과 행동을 사전에 아무것도 추가하지

을 매퍼에 추가 된 위치를지도 할 수 있어야한다. 코어가 누락되었습니다 - 매핑. 나는이 클래스가 어떻게 사용되는지 가정 할 수있다. 매핑을 위해 공용 인터페이스가 필요합니다. 그리고 시험은 (여기에 사용 AutoFixture 및 FluentAssertions)과 같아야합니다 :이 테스트를 통과

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

동안 매퍼 그 위치를 매핑하는 매퍼를 사용하여 위치를 추가 할 수 있습니다.

+0

내 게시물에서 언급했듯이 컨텍스트에 대한 코드를 추가했습니다. 전체가 아닙니다 : - / – karthiks

0

두 가지 옵션이 있습니다. VS Enterprise를 사용하는 경우 Microsoft Fakes를 사용하여 클래스에 대한 Shim을 생성하십시오.

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