As the answers told here work, I do not believe they are clean and correct.
If you want (and you shall) clean code, I offer you ,,mocking".
Suppose the following example:
class CombatController implements ICombatController {
/**
* Protected for being able to test it
*/
protected checkForAttackStyleAndValidate(): boolean {
return false;
}
}
Now, the CombatController
is the class we want to test.
We make checkForAttackStyleAndValidate()
method protected
, because we want to test it. I like to comment above the method that it is protected only for testing purposes.
Now, the actual CombatControllerTest.ts
class CombatControllerMock extends CombatController {
public checkForAttackStyleAndValidate_pub(): boolean {
return super.checkForAttackStyleAndValidate();
}
}
describe() {
it('test', () => {
let cc: CombatControllerMock = new CombatControllerMock ();
assert.equal(cc.checkForAttackStyleAndValidate_pub(), true);
})
}
Discussion
Now, some may argue, that changing private method to protected is unwanted. However, you rarely use inheritance in classes, and if so, when protected is used, you can distinquish whether method is protected only for testing purposes, thanks to the comment. It will be a bit tricky to figure out that some protected method is not supposed to be called from the parent, however, all this logic is encapsulated anyway in the composite class. From the outside, you get a nice class.
Reusability
When needed, you can move the CombatControllerMock into a separate class, and re-use it in different tests. Like this, you can create complex tests for integration tests for complicated instances with multiple dependencies (for example, game objects, such as Players, Spells...)
Customizability
When needed, you can define custom behavior for a specific method, for example, when mocking an abstract class, and you never intend to call that method anyway.
class Player implements IPlayer {
public damage(i: int): boolean{
return false;
}
public abstract giveItem(i: IInventoryItemProto): boolean;
}
So for a test where giveItem()
will never be called, we mock it.
class PlayerMock extends Player {
public giveItem(i: IInventoryItemProto): boolean{ return false; }
}
And you can use PlayerMock in different tests aswell, creating more complex testing mock composites.
Alternative solution
As people here suggested, that you can actually call a private method, which you never shall, it may be used inside the mock _pub() method variant. However, I strongly recommend NOT to call the private method from anywhere else, than testing code, or Mock.