2015-05-11 21 views
6

Używam dwóch metod BitConverter.GetBytes i Array.Reverse do odczytu i zapisu danych binarnych z pliku z powodu endianness.Jak mogę symulować środowisko, w którym BitConverter.IsLittleEndian jest przeciwieństwem moich testów jednostkowych?

Moje testy jednostkowe przechodzą pomyślnie i wdrożenie wydaje się w porządku.

Jak mogę symulować środowisko, w którym BitConverter.IsLittleEndian jest przeciwieństwem moich testów jednostkowych?

+0

Bwahahahahaha ... Nie możesz :-) Ale to jest świetne pytanie! Nawet przy użyciu podróbek, musiałbyś przepisać tyle metod, aby go symulować ... – xanatos

+1

Co powinieneś zrobić: stworzyć klasę otoki wokół BitConvertera, która akceptuje parametr "wymagana endianness" i ma wewnętrzną flagę zawierającą 'BitConverter.IsLittleEndian' które można "zmanipulować" zewnętrznie za pomocą testów jednostkowych. Ta klasa implementuje wszystkie potrzebne metody 'BitConverter', a jeśli' requiredEndianness == savedIsLittleEndian', to znaczy, że używa 'BitConverter', w przeciwnym razie używa' BitConverter + Array.Reverse'. Piszesz testy jednostkowe dla tej klasy i żyjesz szczęśliwy. – xanatos

Odpowiedz

2

Aby rozwinąć mój komentarz: musisz użyć IoC (Inversion of Control), aby wstrzyknąć instancję BitConverterEx tam, gdzie jej potrzebujesz. Ta klasa ma jeden "parametr": endianność wyjścia byte[], które będzie czytać/zapisywać.

W końcu problem ten jest podobny do wspólnego problemu „jak mogę kpić DateTime.Now

W testach jednostkowych, zamiast wstrzykiwania BitConverterEx można wstrzyknąć ManipulableBitConverterEx gdzie można kontrolować flagi procesora. Lub bardziej poprawnie powinieneś przetestować jednostkę niezależnie od BitConverterEx i swoich klas, aby podczas sprawdzania twoich zajęć wiedzieli, że wyniki BitConverterEx są poprawne.

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

Zauważ, że jeśli trzeba ponownie użyć wielokrotnie tej klasy Array.Reverse może być „wolnym”. Istnieją rozwiązania odwracające endianię typów danych, które manipulują pojedynczymi bajtami za pomocą shift, lub, xor, ...

+0

Dzięki za sugestię; Myślę, że to świetne rozwiązanie :) –