2015-05-11 26 views
6

Sto utilizzando i due metodi BitConverter.GetBytes e Array.Reverse per leggere e scrivere dati binari da un file a causa dell'endianness.Come posso simulare un ambiente in cui BitConverter.IsLittleEndian è l'opposto per i miei test di unità?

I test delle unità stanno passando e l'implementazione sembra soddisfacente.

Come è possibile simulare un ambiente in cui BitConverter.IsLittleEndian è l'opposto per i test dell'unità?

+0

Bwahahahahaha ... Non si può :-) Ma è una bella domanda! Anche usando Fakes, dovresti riscrivere tanti metodi per simularlo ... – xanatos

+1

Cosa dovresti fare: creare una classe wrapper attorno a BitConverter che accetta il parametro "endianness richiesto" e ha una bandiera interna contenente il 'BitConverter.IsLittleEndian' che può essere "manipolato" esternamente dai test unitari. Questa classe implementa tutti i metodi necessari di 'BitConverter', e se' requiredEndianness == savedIsLittleEndian', quindi directy usa 'BitConverter', altrimenti usa' BitConverter + Array.Reverse'. Scrivi i test unitari per questa classe e vivi felice. – xanatos

risposta

2

Per espandere il mio commento: sarà necessario utilizzare IoC (Inversion of Control) per iniettare un'istanza BitConverterEx dove è necessario. Questa classe ha un singolo "parametro": l'endianness dell'output byte[] che leggerà/scriverà.

Alla fine questo problema è simile al problema comune "come posso deridere DateTime.Now"

Nei test di unità, invece di iniettare un BitConverterEx è possibile iniettare la ManipulableBitConverterEx cui è possibile controllare il flag processore. O più correttamente dovresti testare in modo indipendente il BitConverterEx e le tue classi, in modo che quando testi le tue classi, sai che i risultati di BitConverterEx sono corretti.

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

Nota che se hai bisogno di riutilizzare molte volte questa classe, Array.Reverse potrebbe essere "lento". Ci sono soluzioni per invertire la endianità dei tipi di dati che manipolano i singoli byte usando shift, o, xor, ...

+0

Grazie per il suggerimento; Penso che questa sia un'ottima soluzione :) –