Create a mock for any instance of a class

2

How do I mock any instance of a class? I would like to do this so I do not have to mock an object and have to put it inside a class. Example:

[TestFixture]
public class TokenTest
{

    GeradorDeToken target;

    [Test]
    public void GeraTokenComSucesso()
    {
        int[] array = { 19, 28, 37, 46, 55 };

        var mockGeradorDeArray = new Mock<GeradorDeArrayParaToken>();

        mockGeradorDeArray.SetupAny(g => g.GeraArray()).Returns(array);

        string tokenEsperado = "1E7C6XB9F8A";

        token = new GeradorDeToken();

        Assert.That(target.GeraToken(), Is.EqualTo(tokenEsperado));
    }


}

public class GeradorDeToken
{
    private int[] arrayNumeros;

    public GeradorDeToken()
    {
        this.arrayNumeros = new GeradorDeArrayParaToken().GeraArray();
    }

    public string GeraToken()
    {
        //Criação do token baseado no arrayNumeros
        return "";
    } 

}

public class GeradorDeArrayParaToken
{

    public virtual int[] GeraArray()
    {
        int[] array = new int[5];

        //Gero numeros randomicos

        return array;
    }
}

I illustrated by creating the dummy method SetupAny (it does not exist in the Moq library). What is the correct way that this framework solves this question?

    
asked by anonymous 02.11.2015 / 12:13

1 answer

3

This is not possible.

To test the GeradorDeToken class using unit tests, we have to isolate it from its dependencies - and this is done through dependency injection. This injection can be done through the constructor, properties (unusual and inadvisable), or parameters of a method. In this case, it looks like you need constructor injection .

public class GeradorDeToken
{
    private int[] arrayNumeros;

    public GeradorDeToken(IGeradorDeArrayParaToken gerador)
    {
        this.arrayNumeros = gerador.GeraArray();
    }

    public string GeraToken() {}    
}

public interface IGeradorDeArrayParaToken {}
public class GeradorDeArrayParaToken : IGeradorDeArrayParaToken {}

If your goal is to avoid re-injecting dependencies in the test, you can use AutoFixture + AutoMoq, an essential testing tool units.

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization()));

// Sempre que uma dependência ou um mock precisar de um objecto to tipo 'int[]', a variável 'array' será usada.
fixture.Inject(array);

var gerador = fixture.Create<GeradorDeToken>(); // As dependencias serao automaticamente injectadas.

Thanks to AutoConfiguredMoqCustomization , mocks of interfaces or abstract classes will be automatically created, and your methods / properties will be setup. There are also plugins for xUnit and NUnit to make it easy to create and customize the fixture.

Two notes about your implementation:

  • Uses an interface instead of a class with a virtual method.
  • The GeraArray method should be called within the GeraToken method and not in the constructor. Otherwise, successive calls to the GeraToken method will always return the same result - I do not think this is the expected behavior.
02.11.2015 / 14:25