Você tem um conflito aqui.
Você deseja testar o valor de retorno de doThings(), que depende de um literal (valor const).
Qualquer teste que você escrever para isso será inerentemente resumido ao testar um valor const , o que não faz sentido.
Para mostrar um exemplo mais sensato (sou mais rápido com C #, mas o princípio é o mesmo)
public class TriplesYourInput : Base
{
public TriplesYourInput(int input)
{
this.foo = 3 * input;
}
}
Esta classe pode ser testada significativamente:
var inputValue = 123;
var expectedOutputValue = inputValue * 3;
var receivedOutputValue = new TriplesYourInput(inputValue).doThings();
Assert.AreEqual(receivedOutputValue, expectedOutputValue);
Isso faz mais sentido para testar. Sua saída é baseada na entrada que você escolheu para fornecer. Nesse caso, você pode dar a uma classe uma entrada escolhida arbitrariamente, observar sua saída e testar se ela corresponde às suas expectativas.
Alguns exemplos deste princípio de teste. Observe que meus exemplos sempre têm controle direto sobre qual é a entrada do método testável.
- Teste se
GetFirstLetterOfString()retorne "F" quando insiro "Flater".
- Teste se
CountLettersInString()retorna 6 quando insiro "Flater".
- Teste se
ParseStringThatBeginsWithAnA()retorna uma exceção quando insiro "Flater".
Todos esses testes podem inserir o valor que quiserem , desde que suas expectativas estejam alinhadas com o que estão inserindo.
Mas se sua saída for decidida por um valor constante, você precisará criar uma expectativa constante e testar se o primeiro corresponde ao segundo. O que é bobagem, isso sempre ou nunca vai passar; nenhum dos quais é um resultado significativo.
Alguns exemplos deste princípio de teste. Observe que esses exemplos não têm controle sobre pelo menos um dos valores que estão sendo comparados.
- Teste se
Math.Pi == 3.1415...
- Teste se
MyApplication.ThisConstValue == 123
Esses testes para um valor específico. Se você alterar esse valor, seus testes falharão. Em essência, você não está testando se sua lógica funciona para qualquer entrada válida, está simplesmente testando se alguém é capaz de prever com precisão um resultado sobre o qual não tem controle.
Isso é essencialmente testar o conhecimento do escritor do teste sobre a lógica de negócios. Não está testando o código, mas o próprio escritor.
Revertendo para o seu exemplo:
class BarDerived : public Base
{
public:
BarDerived() : Base(12) { };
~BarDerived() { };
int doBarThings() { return foo + 1; };
}
Por que BarDerivedsempre tem um fooigual a 12? Qual o significado disso?
E, como você já decidiu isso, o que você está tentando ganhar escrevendo um teste que confirma que BarDerivedsempre é fooigual a 12?
Isso fica ainda pior se você começar a considerar que doThings()pode ser substituído em uma classe derivada. Imagine se você AnotherDeriveddeseja substituir doThings()para que ele sempre retorne foo * 2. Agora, você terá uma classe que é codificada permanentemente Base(12), cujo doThings()valor é 24. Embora tecnicamente testável, é desprovida de qualquer significado contextual. O teste não é compreensível.
Eu realmente não consigo pensar em uma razão para usar essa abordagem de valor codificado. Mesmo se houver um caso de uso válido, não entendo por que você está tentando escrever um teste para confirmar esse valor codificado . Não há nada a ganhar testando se um valor constante é igual ao mesmo valor constante.
Qualquer falha no teste prova inerentemente que o teste está errado . Não há resultado em que uma falha no teste comprove que a lógica de negócios está errada. Você é efetivamente incapaz de confirmar quais testes são criados para confirmar em primeiro lugar.
A questão não tem nada a ver com herança, caso você esteja se perguntando. Você acabou de acontecer de ter usado um valor const no construtor da classe base, mas você poderia ter usado este valor const em qualquer outro lugar e então ele não estaria relacionada a uma classe herdada.
Editar
Há casos em que valores codificados permanentemente não são um problema. (novamente, desculpe pela sintaxe do C #, mas o princípio ainda é o mesmo)
public class Base
{
public int MultiplyFactor;
protected int InitialValue;
public Base(int value, int factor)
{
this.InitialValue = value;
this.MultiplyFactor= factor;
}
public int GetMultipliedValue()
{
return this.InitialValue * this.MultiplyFactor;
}
}
public class DoublesYourNumber : Base
{
public DoublesYourNumber(int value) : base(value, 2) {}
}
public class TriplesYourNumber : Base
{
public TriplesYourNumber(int value) : base(value, 3) {}
}
Enquanto o valor constante ( 2/ 3) ainda está influenciando o valor de saída GetMultipliedValue(), o consumidor da sua classe ainda tem controle sobre ele também!
Neste exemplo, testes significativos ainda podem ser gravados:
var inputValue = 123;
var expectedDoubledOutputValue = inputValue * 2;
var receivedDoubledOutputValue = new DoublesYourNumber(inputValue).GetMultipliedValue();
Assert.AreEqual(expectedDoubledOutputValue , receivedDoubledOutputValue);
var expectedTripledOutputValue = inputValue * 3;
var receivedTripledOutputValue = new TriplesYourNumber(inputValue).GetMultipliedValue();
Assert.AreEqual(expectedTripledOutputValue , receivedTripledOutputValue);
- Tecnicamente, ainda estamos escrevendo um teste que verifica se a const in
base(value, 2)corresponde à const in inputValue * 2.
- No entanto, estamos ao mesmo tempo também testar que esta classe está correctamente multiplicando qualquer valor dado por este fator predeterminado .
O primeiro ponto não é relevante para o teste. O segundo é!
virtual?