Archive for May 17, 2010

Moq e Indexers

Mi framework favorita de mocking es Moq, es flexible, rápida, intuitiva, (dije flexible ya verdad?). Otro día hablaré más detallado de Moq y sus destrezas. Hoy un compañero de trabajo se topó con algo interesante en un test, el mock de una propiedad indexer. Como recordaran, un indexer no es más que una propiedad de una clase que se comporta como la “llave” de esa propiedad, “a-la” diccionario.

La buena noticia es que Moq me permite fácilmente crear mocks de indexers.

Digamos que tenemos la siguiente clase e interface en cuestión:

interface ISimpleStorage {
    string this[string key] { get; set; }
}

interface ISearchDataFiller {
    void FillData(SearchData data);
}

class ClientIPSearchFiller : ISearchDataFiller {
    public readonly string HttpRemoteHostKey = "HTTP_REMOTE_HOST";
    public readonly string RemoteHostKey = "REMOTE_HOST";
    private readonly ISimpleStorage _storage;

    public ClientIPSearchDataFiller(ISimpleStorage storage) {
        _storage = storage;
    }

    public void FillData(SearchData data) {
          var ip = _storage[HttpRemoteHostKey] ?? string.Empty;
                if (string.IsNullOrEmpty(ip))
                    ip = _storage[RemoteHostKey] ?? string.Empty;
                data.IpAddress = ip;
    }
}

Gracias a Moq nuestro test sería algo tan simple como esto (faltan facts, pero ya ustedes se hicieron a la idea :P )

class ClientIPSearchFillerFacts {
    private readonly ClientIPSearchFiller _filler;
    private readonly Mock<ISimpleStorage> _storage;

    public ClientIPSearchFillerFacts() {
        _storage = new Mock<ISimpleStorage>();
        _filler = new ClientIPSearchFiller(_storage.Object);
    }

    [Fact]
    public void When_http_remote_host_appears_use_it() {
        const string ip = "192.168.1.1";
        var data = new SearchData();
        _storage.SetupGet(x => x[data.HttpRemoteHostKey]).Returns(ip);
        _filler.FillData(data);

        _storage.VerifyAll();
        data.IpAddres.Should().Be.EqualTo(ip);
    }

    [Fact]
    public void When_http_remote_host_is_empty_use_remote_host() {
        const string ip = "192.168.1.1";
        var data = new SearchData();
        _storage.SetupGet(x => x[data.HttpRemoteHostKey]).Returns(string.Empty);
        _storage.SetupGet(x => x[data.RemoteHostKey]).Returns(ip)
        _filler.FillData(data);

        _storage.VerifyAll();
        data.IpAddres.Should().Be.EqualTo(ip);
    }
}

Fácil, rápido, simple.

Hasta la próxima!

Stream – CopyTo

Algo común en el manejo de IO en la .Net framework es el lidear con buffers y Streams, a veces simplemente necesitamos copiar el contenido de una stream hacia otra, por ejemplo, cuando necesitamos comprimir (usando GZipStream) o encriptar (usando CryptoStream). Comúnmente hacemos algo como esto:

using (var input = new MemoryStream())
using (var output = new MemoryStream()) {
    var buffer = new byte[input.Length];
    input.Read(buffer, 0, buffer.Length);
    output.Write(buffer, 0, buffer.Length);
}

Y nos topamos con siempre el pedazo de código repetitivo, además de una variable buffer la cual usamos solamente para copiar el contenido. Pues bien, en la .Net Framework 4.0 esto se simplificó un poco con el método CopyTo de la clase abstracta Stream

using (var input = new MemoryStream())
using (var output = new MemoryStream()) {
    input.CopyTo(output);
}

Bastante más conciso a mi criterio :)

Saludos!