Singleton ist aus Testsicht ein besserer Ansatz. Im Gegensatz zu statischen Klassen kann Singleton Schnittstellen implementieren, und Sie können eine Scheininstanz verwenden und diese einfügen.
Im folgenden Beispiel werde ich dies veranschaulichen. Angenommen, Sie haben eine Methode isGoodPrice (), die eine Methode getPrice () verwendet, und Sie implementieren getPrice () als Methode in einem Singleton.
Singleton mit getPrice-Funktionalität:
public class SupportedVersionSingelton {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
// calculate price logic here
return 0;
}
}
Verwendung von getPrice:
public class Advisor {
public boolean isGoodDeal(){
boolean isGoodDeal = false;
ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
int price = supportedVersion.getPrice();
// logic to determine if price is a good deal.
if(price < 5){
isGoodDeal = true;
}
return isGoodDeal;
}
}
In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it.
public interface ICalculator {
int getPrice();
}
Endgültige Singleton-Implementierung:
public class SupportedVersionSingelton implements ICalculator {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
return 0;
}
// for testing purpose
public static void setInstance(ICalculator mockObject){
if(instance != null ){
instance = mockObject;
}
Testklasse:
public class TestCalculation {
class SupportedVersionDouble implements ICalculator{
@Override
public int getPrice() {
return 1;
}
}
@Before
public void setUp() throws Exception {
ICalculator supportedVersionDouble = new SupportedVersionDouble();
SupportedVersionSingelton.setInstance(supportedVersionDouble);
}
@Test
public void test() {
Advisor advidor = new Advisor();
boolean isGoodDeal = advidor.isGoodDeal();
Assert.assertEquals(isGoodDeal, true);
}
}
Wenn wir die Alternative der Verwendung einer statischen Methode zur Implementierung von getPrice () wählen, war es schwierig, getPrice () zu verspotten. Sie könnten statisch mit Power-Mock verspotten, aber nicht alle Produkte könnten es verwenden.
getInstance()
Methode jedes Mal aufgerufen werden muss, wenn Sie sie verwenden möchten (obwohl dies in den meisten Fällen wahrscheinlich keine Rolle spielt ).