Moin,
in einer geschlossenen Anwendung, würde ich die oben erwähnten Utility-Klassen etwa so implementieren:
Interface:
public interface Utilities {
/**
* Do some magic
*
* @param input
* @return
*/
int method(final int input);
}```
Implementierung:
```package net.mschorn.kskb.utilities;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public final class UtilitiesImpl implements Utilities {
private static final int MAGIC = 42;
@Inject
private UtilitiesImpl() {
}
@Override
public int method(final int input) {
return input * MAGIC;
}
}
Verwendung der Utility-Methode:
import javax.inject.Inject;
import net.mschorn.kskb.utilities.Utilities;
public final class Use {
private final Utilities utilities;
@Inject
private Use(final Utilities utilities) {
this.utilities = utilities;
}
public int use(final int input) {
return utilities.method(input) + 7;
}
}```
Und im Test sähe das dann etwa so aus:
Test für die Utility-Methode:
```package net.mschorn.kskb.utilities;
import static org.testng.Assert.assertEquals;
import mockit.Tested;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public final class UtilitiesImplTest {
@Tested
private UtilitiesImpl utilities;
@DataProvider(name = "method")
public Object[][] createData() {
return new Object[][] {
{ 0, 0 },
{ 1, 42 },
{ 2, 84 }
};
}
@Test(dataProvider = "method")
public void method(final int input, final int expected) {
assertEquals(utilities.method(input), expected);
}
}```
Test des Verwenders mit Mock der Utility-Klasse:
```package net.mschorn.kskb.main;
import static org.testng.Assert.assertEquals;
import mockit.Expectations;
import mockit.Injectable;
import mockit.Tested;
import net.mschorn.kskb.utilities.Utilities;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public final class UseTest {
@Tested
private Use use;
@Injectable
private Utilities utilities;
@DataProvider(name = "use")
public Object[][] createData() {
return new Object[][] {
{ 0, 7 },
{ 1, 8 },
{ 2, 9 }
};
}
@Test(dataProvider = "use")
public void use(final int input, final int expected) {
new Expectations() {
{
utilities.method(input);
returns(input);
}
};
assertEquals(use.use(input), expected);
}
}```
So entsteht natürlich etwas Tipparbeit, aber es ist einfach zu schreiben, einfach zu testen und skaliert beliebig. Problematisch kann es werden, wenn man das so in einer offenen Library implementiert, da man den Verwender zu DI zwingt. Ob das wirklich immer ein Nachteil ist, weiß ich aber nicht.
Viele Grüße
Fancy