La première année des nouveaux diplômés est presque terminée. En utilisant le cadre de Spock, je suis tombé sur diverses façons de se moquer de Mockito et de Spock, alors j'ai fait un mémorandum et l'ai partagé pour des personnes similaires. Il serait préférable de créer une instance dans la situation réelle sans se moquer du code décrit ici, mais ce n'est qu'un exemple ...
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// https://mvnrepository.com/artifact/org.spockframework/spock-core
testCompile group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5'
// https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-all
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.5.6', ext: 'pom'
}
Il est publié sur GitHub.
Mockito
Utilisez when --then Return
pour définir la valeur renvoyée par le simulacre. Puisque spockComponent1Factory est la cible de l'injection, ajoutez l'annotation ʻinitMocks et ʻInjectMocks
dans setup
. Il semble que vous puissiez vérifier le nombre de fois en écrivant true
dans la partie verify
, mais cela semble très étrange ...
SpockComponent1FactoryTest.groovy
@InjectMocks
SpockComponent1Factory spockComponent1Factory
@Mock
SpockComponent2Factory spockComponent2Factory
@Mock
SpockComponent2 spockComponent2
@Mock
SpockComponent3 spockComponent3
@Mock
SpockComponent4 spockComponent4
def setup() {
initMocks(this)
}
def "GetValueFromSpockComponent4 -Vérifiez le nombre d'appels"() {
given:
when(spockComponent2Factory.create(any(Integer.class))).thenReturn(spockComponent2)
when(spockComponent2.getSpockComponent3()).thenReturn(spockComponent3)
when(spockComponent3.getSpockComponent4()).thenReturn(spockComponent4)
when:
spockComponent1Factory.getValueFromSpockComponent4(0)
then:
verify(spockComponent2Factory, times(1)).create(any(Integer.class)) || true
}
Utilisez RETURN_DEEP_STUBS
pour simuler des instances imbriquées. En réécrivant le test ci-dessus, il peut être écrit comme suit.
SpockComponent1FactoryTestAlt.groovy
@InjectMocks
SpockComponent1Factory spockComponent1Factory
@Mock
SpockComponent2Factory spockComponent2Factory
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
SpockComponent2 spockComponent2
@Mock
SpockComponent4 spockComponent4
def setup() {
initMocks(this)
}
def "getValueFromSpockComponent -Pause de vérification du nombre d'appels"() {
given:
when(spockComponent2Factory.create(any(Integer.class))).thenReturn(spockComponent2)
when(spockComponent2.getSpockComponent3().getSpockComponent4()).thenReturn(spockComponent4)
when:
spockComponent1Factory.getValueFromSpockComponent4(0)
then:
verify(spockComponent2Factory, times(1)).create(any(Integer.class)) || true
}
Spock
Un test similaire écrit en Spock ressemble à ceci: Si vous voulez vérifier le nombre d'exécutions, il semble que le test ne passera pas à moins que vous ne vous moquiez et ne stub en même temps dans la clause then
. Au fait, dans Spock, si vous voulez remplacer le comportement défini dans setup
par des cas de test individuels, il semble que vous deviez le faire dans la clause then
. (Référence: Stackoverflow-Official Document)
SpockComponent1FactoryTestSpock.groovy
SpockComponent1Factory spockComponent1Factory
SpockComponent2Factory spockComponent2Factory
SpockComponent2 spockComponent2
SpockComponent3 spockComponent3
SpockComponent4 spockComponent4
def setup() {
spockComponent2Factory = Mock(SpockComponent2Factory.class)
spockComponent2 = Mock(SpockComponent2.class)
spockComponent3 = Mock(SpockComponent3.class)
spockComponent4 = Mock(SpockComponent4.class)
}
def "GetValueFromSpockComponent4 -La vérification du nombre d'appels a échoué"() {
given:
spockComponent3.getSpockComponent4() >> spockComponent4
spockComponent2.getSpockComponent3() >> spockComponent3
spockComponent2Factory.create(_ as Integer) >> spockComponent2
when:
spockComponent1Factory = new SpockComponent1Factory(spockComponent2Factory)
spockComponent1Factory.getValueFromSpockComponent4(0)
then:
1 * spockComponent2Factory.create(_ as Integer)
}
def "GetValueFromSpockComponent4 -Vérification du nombre d'appels réussie"() {
given:
spockComponent3.getSpockComponent4() >> spockComponent4
spockComponent2.getSpockComponent3() >> spockComponent3
when:
spockComponent1Factory = new SpockComponent1Factory(spockComponent2Factory)
spockComponent1Factory.getValueFromSpockComponent4(0)
then:
1 * spockComponent2Factory.create(_ as Integer) >> spockComponent2
}
Spock a également besoin d'ingéniosité pour simuler des instances imbriquées. Moins que.
SpockComponent1FactoryTestSpockAlt.groovy
SpockComponent1Factory spockComponent1Factory
SpockComponent2Factory spockComponent2Factory
SpockComponent2 spockComponent2
SpockComponent4 spockComponent4
def setup() {
spockComponent2Factory = Mock(SpockComponent2Factory.class)
spockComponent2 = Mock(SpockComponent2.class)
spockComponent4 = Mock(SpockComponent4.class)
}
def "GetValueFromSpockComponent4 -Pause de vérification du nombre d'appels"() {
given:
spockComponent2.getSpockComponent3() >> {
Mock(SpockComponent3.class) {
getSpockComponent4() >> spockComponent4
}
}
when:
spockComponent1Factory = new SpockComponent1Factory(spockComponent2Factory)
spockComponent1Factory.getValueFromSpockComponent4(0)
then:
1 * spockComponent2Factory.create(_ as Integer) >> spockComponent2
}
Dans le code d'implémentation, null est directement placé dans la méthode qui prend l'argument de String.
SpockComponent1Factory.java
public void nullArgumentMethodCall() {
spockComponent2Factory.nullArgumentMethodCalled(null);
}
Mockito
J'ai utilisé nullable ()
parce que je ne pouvais pas le vérifier avec ʻany () `.
SpockComponent1FactoryTest.groovy
@InjectMocks
SpockComponent1Factory spockComponent1Factory
@Mock
SpockComponent2Factory spockComponent2Factory
@Mock
SpockComponent2 spockComponent2
@Mock
SpockComponent3 spockComponent3
@Mock
SpockComponent4 spockComponent4
def setup() {
initMocks(this)
}
def "NullArgumentMethodCall -La vérification du nombre d'appels a échoué"() {
when:
spockComponent1Factory.nullArgumentMethodCall()
then:
verify(spockComponent2Factory, times(1)).nullArgumentMethodCalled(any(String.class)) || true
}
def "NullArgumentMethodCall -Vérification du nombre d'appels réussie"() {
when:
spockComponent1Factory.nullArgumentMethodCall()
then:
verify(spockComponent2Factory, times(1)).nullArgumentMethodCalled(nullable(String.class)) || true
}
Spock Le côté Spock a fonctionné sans aucun problème.
SpockComponent1FactoryTestSpock.groovy
SpockComponent1Factory spockComponent1Factory
SpockComponent2Factory spockComponent2Factory
SpockComponent2 spockComponent2
SpockComponent3 spockComponent3
SpockComponent4 spockComponent4
def setup() {
spockComponent2Factory = Mock(SpockComponent2Factory.class)
spockComponent2 = Mock(SpockComponent2.class)
spockComponent3 = Mock(SpockComponent3.class)
spockComponent4 = Mock(SpockComponent4.class)
}
def "NullArgumentMethodCall -Vérifiez le nombre d'appels"() {
when:
spockComponent1Factory = new SpockComponent1Factory(spockComponent2Factory)
spockComponent1Factory.nullArgumentMethodCall()
then:
spockComponent2Factory.nullArgumentMethodCalled(_ as String)
}
}
Comme je l'ai mentionné au début, il peut être possible de rendre le code de test plus lisible en créant réellement une instance qu'en se moquant de celle-ci, il semble donc préférable de l'écrire en réfléchissant (également comme un commandement pour vous-même).
Recommended Posts