2014-03-07 3 views
3

많은 필드가있는 거대한 객체를 반환하는 메소드가 있습니다. 다음과 같은 것 :퍼지 깊이 객체 비교

{ 
    Success: true, 
    Timestamp: "07.03.2014", 
    Items: 
    [ 
     { 
      Name: "A", 
      Price: 13.37, 
      OtherData: 123 
     }, 
     { 
      Name: "B", 
      Price: 42, 
      OtherData: 312 
     } 
    ] 
} 

반환 값과 .NET 응용 프로그램 테스트의 참조 값을 비교하고 싶습니다. 그러나 몇 가지 문제가 여기에있다 :

  • Timestamp 필드마다
  • 을 변경 Price 필드의 라운딩도
  • Items의 순서는 다를 수 있습니다 것은

나는 것 중요하지 않다 가능하면 가장 유연한 방법으로 참조 객체를 정의하는 것이 좋습니다.

  • 개 생략 불필요한 필드뿐만 아니라 값,하지만 규칙을 지정할 수 있다는
  • 여기

가 기준 정의가 같이하는 방법의 예 (문자열에 대한 정규 표현식을,/등등, 숫자 반올림 범위) :

이러한 비교를 허용하는 .NET 용 라이브러리가 있습니까?

답변

2

결국 나는 직접 비교를 구현하기로 결정했습니다. 여기에 코드입니다, 어쩌면 누군가에게 유용 할 것입니다 : 내가 시간이 충분하면

public static class Utils 
{ 
    public static bool SequencesMatch<TSource, TPattern>(IEnumerable<TSource> sequence, IEnumerable<TPattern> patterns, Func<TSource, TPattern, bool> matcher) 
    { 
     var items = sequence.Select(x => new SequenceItem<TSource>(x)).ToArray(); 
     var pats = patterns.Select(x => new SequenceItem<TPattern>(x)).ToArray(); 

     foreach (var item in items) 
     { 
      foreach (var pat in pats) 
      { 
       if (pat.Matched) continue; 
       if (matcher(item.Value, pat.Value)) 
       { 
        item.Matched = pat.Matched = true; 
        break; 
       } 
      } 
     } 

     return items.All(x => x.Matched) && pats.All(x => x.Matched); 
    } 

    public static bool JsonObjectsMatch(JToken data, JToken reference) 
    { 
     if (reference.Type == JTokenType.Array) 
      return SequencesMatch(data, reference, JsonObjectsMatch); 

     if (reference.Type == JTokenType.Object) 
     { 
      var dataObj = data as JObject; 
      var refObj = reference as JObject; 

      if (dataObj == null || refObj == null) 
       Assert.Fail("DataObject = '{0}', ReferenceObject = '{1}'", dataObj, refObj); 

      foreach (var pty in refObj) 
      { 
       var dataValue = dataObj[pty.Key]; 
       if (dataValue == null || !JsonObjectsMatch(dataValue, pty.Value)) 
        Assert.Fail("Objects differ at {0}: DataValue = '{1}', RefValue = '{2}'", pty.Key, dataValue, pty.Value); 
      } 

      return true; 
     } 

     if (reference.Type == JTokenType.Float) 
     { 
      var refFloat = reference.ToObject<float>(); 
      var dataFloat = data.ToObject<float>(); 

      if(Math.Abs(dataFloat - refFloat) > 0.001) 
       Assert.Fail("Objects differ: DataValue = '{0}', RefValue = '{1}'", dataFloat, refFloat); 

      return true; 
     } 

     return JToken.DeepEquals(data, reference); 
    } 

    private class SequenceItem<T> 
    { 
     public T Value { get; set; } 
     public bool Matched { get; set; } 

     public SequenceItem(T value) 
     { 
      Value = value; 
     } 
    } 
} 

내가 아마 GitHub의에 적절한 라이브러리 및 사후해야한다.

+0

예, 그렇습니다. 이 함수에 대한 몇 가지 유스 케이스를 볼 수있다 :) – ForNeVeR