2015-05-11 11 views
6

Ich verwende die beiden Methoden BitConverter.GetBytes und Array.Reverse, um binäre Daten aus einer Datei aufgrund der Endianz zu lesen und zu schreiben.Wie kann ich eine Umgebung simulieren, in der BitConverter.IsLittleEndian für meine Komponententests das Gegenteil ist?

Meine Komponententests sind vorüber und die Implementierung scheint in Ordnung zu sein.

Wie kann ich eine Umgebung simulieren, in der BitConverter.IsLittleEndian das Gegenteil für meine Komponententests ist?

+0

Bwahahahahaha ... Sie können nicht :-) Aber es ist eine gute Frage! Selbst mit Fakes müssten Sie so viele Methoden umschreiben, um es zu simulieren ... – xanatos

+1

Was Sie tun sollten: Erstellen Sie eine Wrapper-Klasse um BitConverter, die den Parameter "erforderliche Endianness" akzeptiert und intern ein Flag enthält, das den 'BitConverter.IsLittleEndian' enthält das kann extern durch Unit Tests "manipuliert" werden. Diese Klasse implementiert alle benötigten Methoden von 'BitConverter', und wenn' requiredEndianness == savedIsLittleEndian', dann verwendet sie direkt 'BitConverter', andernfalls' BitConverter + Array.Reverse'. Sie schreiben die Unit Tests für diese Klasse und leben glücklich. – xanatos

Antwort

2

Um meinen Kommentar zu erweitern: Sie müssen IoC (Inversion of Control) verwenden, um eine BitConverterEx Instanz zu injizieren, wo Sie es brauchen. Diese Klasse hat einen einzigen "Parameter": die Endianz der Ausgabe byte[], die gelesen/geschrieben wird.

Am Ende dieses Problem mit dem gemeinsamen Problem ähnlich ist: „Wie kann ich verspotten DateTime.Now

In den Unit-Tests, anstatt eine BitConverterEx der Injektion Sie die ManipulableBitConverterEx injizieren können, wo Sie den Prozessor-Flag steuern kann. Oder genauer gesagt sollten Sie Unit BitConverterEx und Ihre Klassen unabhängig voneinander testen, so dass Sie beim Testen Ihrer Klassen wissen, dass die Ergebnisse von BitConverterEx korrekt sind.

public class BitConverterEx 
{ 
    public bool ProcessorLittleEndian { get; protected set; } 
    public bool DataLittleEndian { get; protected set; } 

    public BitConverterEx(bool dataLittleEndian) 
    { 
     ProcessorLittleEndian = BitConverter.IsLittleEndian; 
     DataLittleEndian = dataLittleEndian; 
    } 

    public byte[] GetBytes(int value) 
    { 
     byte[] bytes = BitConverter.GetBytes(value); 

     if (DataLittleEndian != ProcessorLittleEndian) 
     { 
      Array.Reverse(bytes); 
     } 

     return bytes; 
    } 

    public int ToInt32(byte[] value, int startIndex) 
    { 
     if (DataLittleEndian == ProcessorLittleEndian) 
     { 
      return BitConverter.ToInt32(value, startIndex); 
     } 

     byte[] value2 = new byte[sizeof(int)]; 
     Array.Copy(value, startIndex, value2, 0, value2.Length); 
     Array.Reverse(value2); 
     return BitConverter.ToInt32(value2, 0); 
    } 
} 

public class ManipulableBitConverterEx : BitConverterEx 
{ 
    public ManipulableBitConverterEx(bool processorLittleEndian, bool dataLittleEndian) 
     : base(dataLittleEndian) 
    { 
     ProcessorLittleEndian = processorLittleEndian; 
    } 
} 

Beachten Sie, dass, wenn Sie viele Male diese Klasse wieder verwenden müssen, Array.Reverse „langsam“ sein könnte. Es gibt Lösungen zum Invertieren der Endianität von Datentypen, die die einzelnen Bytes mit Hilfe von shift manipulieren, oder, xor, ...

+0

Danke für den Vorschlag; Ich denke, das ist eine großartige Lösung :) –