2013-05-29 18 views
13

Combiniamo i test di Spock con Spring @ContextConfiguration in modo che possiamo creare bean in un contesto primaverile e quindi utilizzare Spock per i test effettivi. Vorremmo iniettare mock spock nei nostri fagioli primaverili. Per Mockito c'è un'estensione che ti permette di fare cose come:Come creare Spock mock al di fuori di una classe di specifiche?

<mockito:mock id="accountService" class="org.kubek2k.account.DefaultAccountService" /> 

e quindi fare riferimento a questo simulato ad altri fagioli di primavera. Sembra che non ci sia un'estensione di questo tipo per Spock. Quindi, costruire di nuovo questo probabilmente non è troppo difficile se sai come creare Mock al di fuori della classe Specification. L'unico modo per creare un Spock Mock di cui sono a conoscenza è:

T Mock(Class<T> type) 

in Specifica. C'è qualche API in Spock per creare Mock quando non si trova all'interno della classe Specification, quindi potrei creare Spock Mock per un contesto primaverile?

risposta

6

La creazione di mock al di fuori di una classe di specifiche (e il loro utilizzo in un'altra classe spec) non è attualmente possibile. C'è una richiesta di funzionalità aperta per questo. Non dovrebbe essere troppo difficile da implementare, ma richiederebbe alcune modifiche a Spock-Core. Per lo meno, ci dovrebbe essere un modo per collegare manualmente un oggetto fittizio ad un'altra istanza spec. Probabilmente, avrebbe anche senso spostare l'API di creazione simulata rivolta all'utente fuori dalla classe base MockingApi.

Dovresti essere in grado di utilizzare Mockito con Spock, a patto che completi tutto il codice di verifica contenuto in un blocco con una chiamata a un metodo di supporto che restituisce true (perché Spock lo considererà un'asserzione). Qualcosa come then: mockito { /* mockito verifications go here */ }.

+4

Sono seduto in SpringOne Spock e testMvc sess e sta iniziando a sembrare ovvio che, al fine di mixare alcuni servizi e alcuni servizi configurati da Spring (ad esempio per evitare di avere una logica di integrazione al di fuori del test) questa funzionalità sarebbe molto utile. –

+0

Forse SpecificationMixin è quello che stavo cercando? –

+0

Non ho familiarità con 'SpecificationMixin'. C'è una richiesta di pull nei lavori che permette la costruzione esterna di mock, e speriamo che verrà spedita con la prossima versione di Spock. –

5

È stata trovata una soluzione semplice per utilizzare gli oggetti mock di Spock in un'applicazione Spring. Ecco la mia configurazione primavera per usare un mock per il bean Basar:

@Configuration @Profile("mocking") 
class MockingContext { 
    @Bean Basar basar(){ new DelegatingBasar() } 
} 

class DelegatingBasar implements Basar { 
    @Delegate Basar delegate 
} 

E qui una semplice specificazione Spock che crea e utilizza un finto:

@Autowired 
Basar basar 
Basar basarMock 

def setup() { 
    basarMock = Mock(Basar) 
    basar.delegate = basarMock; 
} 

def "create a new seller"(User seller) { 
    given: 
     basarMock.findAllUsers() >> [] 
    when: 
     go "/static/sellers.html" 
     waitFor { $("#newUser") } 
     $("#newUser").click() 
     waitFor { $("#basarNumber") } 
     $("#basarNumber").value(seller.basarNumber) 
     $("#name").value(seller.name) 
     $("#lastname").value(seller.lastname) 
     $("#email").value(seller.email) 
     $("#saveUser").click() 
     waitFor { $("#successfullCreated") } 
    then: 
     1 * basarMock.saveUser({ newUser -> 
      newUser.basarNumber == seller.basarNumber 
      newUser.name  == seller.name 
      newUser.lastname == seller.lastname 
      newUser.email  == seller.email 
     }) 
    where: 
     seller << [ new User(basarNumber: "100", name: "Christian", lastname: "", email: ""), 
        new User(basarNumber: "ABC", name: "",   lastname: "", email: "")] 
} 
+1

Questa è una soluzione ordinata :). Nel frattempo ci siamo spostati su un approccio più leggero. Cerchiamo di stare alla larga dalla costruzione di contesti primaverili nei nostri test unitari e semplicemente prendiamo in giro da soli tutte le dipendenze (consultate https://gist.github.com/derkork/45d7fba64b54a41608e1). Ciò ha aumentato significativamente il nostro throughput di test. Usiamo solo la molla per cose complesse come i test DAO, dove giriamo affermazioni reali contro un database in memoria. –

0

Questo è abbastanza straight-forward con "puro Primavera ":

def parentAppCtx = new StaticApplicationContext() 
parentAppCtx.beanFactory.registerSingleton("myBean", Mock(MyClass)) 
parentAppCtx.refresh() 
def appCtx = new ClassPathXmlApplicationContext("spring-config.xml", parentAppCtx) 

Ovviamente si presuppone che si stia correttamente decomprimendo la configurazione Spring. (Ad esempio, se si ridefinisce "myBean" in spring-config.xml verrà utilizzato nella definizione spring-config.xml, dal momento che ApplicationContext è essenzialmente una mappa e la definizione più recente mettere in esso vincerà.)

1

Creazione di mock al di fuori di una specifica classe è possibile da Spock 1.1 con DetachedMockFactory e SpockMockFactoryBean. È supportato anche lo spazio dei nomi spock per la configurazione basata su XML. È possibile trovare esempi di utilizzo in the documentation.

Un test primavera utilizzando la configurazione basata su Java e DetachedMockFactory si presenta così:

@ContextConfiguration(classes = [TestConfig, DiceConfig]) 
class DiceSpec extends Specification { 
    @Autowired 
    private RandomNumberGenerator randomNumberGenerator 

    @Subject 
    @Autowired 
    private Dice dice 

    def "uses the random number generator to generate results"() { 
     when: 
      dice.roll() 

     then: 
      1 * randomNumberGenerator.randomInt(6) 
    } 

    static class TestConfig { 
     private final mockFactory = new DetachedMockFactory() 

     @Bean 
     RandomNumberGenerator randomNumberGenerator() { 
      mockFactory.Mock(RandomNumberGenerator) 
     } 
    } 
} 

@Configuration 
class DiceConfig { 
    @Bean 
    Dice dice(RandomNumberGenerator randomNumberGenerator) { 
     new Dice(randomNumberGenerator) 
    } 
} 

e basato su XML di configurazione sarebbe simile a questa:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:spock="http://www.spockframework.org/spring" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans.xsd 
      http://www.spockframework.org/spring http://www.spockframework.org/spring/spock.xsd"> 
    <spock:mock id="randomNumberGenerator" class="RandomNumberGenerator"/> 
</beans> 

Assicurati di includere il spock-spring dipendenze:

testCompile group: 'org.spockframework', name: 'spock-spring', version: '1.1-groovy-2.4-rc-3' 
Problemi correlati