24
Code Smell 82 - Tests Violating Encapsulation
Objects work fine and fulfill business objectives. But we need to test them. Let's break them.
TL;DR: Don't write methods with the only purpose of being used in your tests.
Encapsulation Violation.
Bad interfaces
Coupling
Don't break encapsulation.
Test must be in full control.
If you cannot control your object, you are coupled. Decouple them!
<?
class Hangman {
private $wordToGuess;
function __construct() {
$this->wordToGuess = getRandomWord();
//Test is not in control of this
}
public function getWordToGuess(): string {
return $this->wordToGuess;
}
}
class HangmanTest extends TestCase {
function test01WordIsGuessed() {
$hangmanGame = new Hangman();
$this->assertEquals('tests', $hangmanGame->wordToGuess());
//how can we make sure the word is guessed?
}
}
<?
class Hangman {
private $wordToGuess;
function __construct(WordRandomizer $wordRandomizer) {
$this->wordToGuess = $wordRandomizer->newRandomWord();
}
}
class MockRandomizer implements WordRandomizer {
function newRandomWord(){
return 'tests';
}
}
class HangmanTest extends TestCase {
function test01WordIsGuessed() {
$hangmanGame = new Hangman(new MockRandomizer());
$this->assertFalse($hangmanGame->wordWasGuessed());
$hangmanGame->play('t');
$this->assertFalse($hangmanGame->wordWasGuessed());
$hangmanGame->play('e');
$this->assertFalse($hangmanGame->wordWasGuessed());
$hangmanGame->play('s');
$this->assertTrue($hangmanGame->wordWasGuessed());
//We just test behavior
}
}
This is a design smell.
We can detect we need a method just for test.
- Information Hiding
White-box tests are fragile. They test implementation instead of behavior.
This smell was inspired by @Rodrigo
Don't write methods with the only purpose of being used in your tests
Test the code how it must be used; the more real you can
In a hangman game, you don't expose a method to know the secret word. You test how the game behaves when you guess or miss letters
#cleanCode12:00 PM - 24 Jun 2021
Nothing makes a system more flexible than a suite of tests.
Robert Martin
This article is part of the CodeSmell Series.
24