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.