Springockito - výroba mocků snadno a rychle
Na tento poklad narazil kolega Jakub Liška, když si sám chtěl napsat něco podobného. Pokud používáte pro automatické testy podporu Springu a na vytváření mocků Mockito, máte řadu možností jak vytvářet mock objekty. Jednu z nich, která se mi zdála poměrně jednoduchá jsem popisoval v dřívějším článku Jak se zbavit nepříjemných závislostí v testech, nicméně tento přístup dotáhl Jakub Janczak o kus dál (jo na světě jsou milóny lidí chytřejších jak já :) ).
Problém mého přístupu spočívá v tom, že pro různé konstelace musíte vytvářet řadu doplňkových XML souborů s factory beanami. Navíc musíte dané beany vypárat z původních konfiguračních souborů, aby se daly jednoduše zaměňovat. Knihovna s názvem Springockito vám pomocí jednoduchých anotací @ReplaceWithMock popř. @WrapWithSpy umožní beze změny odkazovaných XML Spring konfigurací nahradit konkrétní beanu mockem a danou instanci i Spring použije při wiringu ostatních bean.
Integrace do projektu je jednoduchá - stačí pro testy přilinkovat tyto dvě knihovny:
<dependencies>
...
<dependency>
<groupId>org.kubek2k</groupId>
<artifactId>springockito</artifactId>
<version>1.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.kubek2k</groupId>
<artifactId>springockito-annotations</artifactId>
<version>1.0.2</version>
<scope>test</scope>
</dependency>
...
</dependencies>
A následně v konfiguraci testů vyměnit třídu pro nahrávání kontextu + použít anotaci @ReplaceWithMock u privátního pole testovací třídy. Springockito se postará o nalezení beany s názvem odpovídajícím názvu pole (a samozřejmě odpovídajícím typem) a nahradí jej vygenerovaným mockem:
@ContextConfiguration(
loader = SpringockitoContextLoader.class,
locations = "classpath:/context.xml"
)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringockitoAnnotationsMocksIntegrationTest {
@ReplaceWithMock
private InnerBean innerBean;
...
}
Doposud nevyřešený problém je úklid mocku po proběhnutí testu (issue 6). Testovací podpora Springu totiž cachuje inicializované Spring kontexty mezi testy (pokud nepoužijete anotaci @DirtiesContext) a tudíž instruovaný mock včetně svého aktuální stavu se SDÍLÍ MEZI TESTY. Z toho důvodu vám mohou a budou dva testy pracující s mockem spuštěné za sebou failovat (ten druhý v pořadí). Naštěstí je možné v Mockitu resetovat stav mocků, připravený právě pro tyto situace (v jiných je naopak doporučováno jej nepoužívat). O reinicializaci mocků se však musíte postarat sami následujícím způsobem:
@After
public void clearMocks() {
Mockito.reset(innerBean)
}
Z výpisu chyb a commit logu je patrné, že projekt má velmi nízkou úroveň aktivity a pouze jediného commitera. To ovšem nic nemění na tom, že nápad je to velmi zajímavý a implementace velmi jednoduchá. Pokud je Vám použití sympatické, myslím, že Jakub Janczak uvítá jakýkoliv pull request.
Komentáře