Recentemente, discuti com alguns amigos qual dos 2 métodos a seguir é melhor para stub retornar resultados ou chamadas para métodos dentro da mesma classe e métodos dentro da mesma classe.
Este é um exemplo muito simplificado. Na realidade, as funções são muito mais complexas.
Exemplo:
public class MyClass
{
public bool FunctionA()
{
return FunctionB() % 2 == 0;
}
protected int FunctionB()
{
return new Random().Next();
}
}
Então, para testar isso, temos 2 métodos.
Método 1: Use Funções e Ações para substituir a funcionalidade dos métodos. Exemplo:
public class MyClass
{
public Func<int> FunctionB { get; set; }
public MyClass()
{
FunctionB = FunctionBImpl;
}
public bool FunctionA()
{
return FunctionB() % 2 == 0;
}
protected int FunctionBImpl()
{
return new Random().Next();
}
}
[TestClass]
public class MyClassTests
{
private MyClass _subject;
[TestInitialize]
public void Initialize()
{
_subject = new MyClass();
}
[TestMethod]
public void FunctionA_WhenNumberIsOdd_ReturnsTrue()
{
_subject.FunctionB = () => 1;
var result = _subject.FunctionA();
Assert.IsFalse(result);
}
}
Método 2: Tornar os membros virtuais, derivar classe e na classe derivada usar Funções e Ações para substituir a funcionalidade Exemplo:
public class MyClass
{
public bool FunctionA()
{
return FunctionB() % 2 == 0;
}
protected virtual int FunctionB()
{
return new Random().Next();
}
}
public class TestableMyClass
{
public Func<int> FunctionBFunc { get; set; }
public MyClass()
{
FunctionBFunc = base.FunctionB;
}
protected override int FunctionB()
{
return FunctionBFunc();
}
}
[TestClass]
public class MyClassTests
{
private TestableMyClass _subject;
[TestInitialize]
public void Initialize()
{
_subject = new TestableMyClass();
}
[TestMethod]
public void FunctionA_WhenNumberIsOdd_ReturnsTrue()
{
_subject.FunctionBFunc = () => 1;
var result = _subject.FunctionA();
Assert.IsFalse(result);
}
}
Quero saber o que é melhor e também POR QUE?
Atualização: NOTA: A FunctionB também pode ser pública
FunctionB
está quebrado por design. new Random().Next()
quase sempre está errado. Você deve injetar a instância de Random
. ( Random
É também uma classe mal concebidos, o que pode causar alguns problemas adicionais)
FunctionA
retorna um bool, mas apenas define uma variável localx
e não retorna nada.