2017-05-04 2 views
3
appelé deux fois

je le code suivant écrit en Scala, Guice, Mockito et ScalaTestScala Mockito Guice et Mocking partiel .... méthodes se

import javax.inject.Singleton 
import com.google.inject.Inject 
@Singleton 
class TestPartialMock @Inject()(t1: Test1, t2: Test2) { 
    def test3() = "I do test3" 
    def workHorse() : List[String] = { 
     println("+++++ came inside ++++++++") 
     List(t1.test1(), t2.test2(), test3()) 
    } 
} 


class MainModule extends ScalaModule { 
    override def configure() = { 
     bind[Test1] 
     bind[Test2] 
     bind[TestPartialMock] 
    } 
} 

et j'ai écrit des cas de tests unitaires avec moqueuse

partielle
class PartialMockTest extends FunSpec with Matchers { 
    describe("we are testing workhorse but mock test3") { 
     it("should return mock for test3") { 
     val module = new TestModule 
     val injector = Guice.createInjector(module) 
     val tpm = injector.getInstance(classOf[TestPartialMock]) 
     val result = tpm.workHorse() 
     result should contain ("i do test2") 
     result should contain ("i do test1") 
     result should contain ("I am mocked") 
     result should not contain ("I do test3") 
     } 
    } 
} 

class TestModule extends AbstractModule with ScalaModule with MockitoSugar { 
    override def configure() = { 
     val module = new MainModule() 
     val injector = Guice.createInjector(module) 
     val realobject = injector.getInstance(classOf[TestPartialMock]) 
     val x = spy(realobject) 
     when(x.test3()).thenReturn("I am mocked") 
     when(x.workHorse()).thenCallRealMethod() 
     bind(classOf[TestPartialMock]).toInstance(x) 
    } 
} 

Mes tests sont réussis et je peux voir qu'il se moque du bon ensemble de méthodes et appelle l'implémentation réelle du bon ensemble de méthodes. Mais quand je regarde la sortie que je vois

info] Compiling 5 Scala sources to /Users/IdeaProjects/GuicePartialMock/target/scala-2.12/classes... 
[info] Compiling 1 Scala source to /Users/IdeaProjects/GuicePartialMock/target/scala-2.12/test-classes... 
+++++ came inside ++++++++ 
+++++ came inside ++++++++ 
[info] PartialMockTest: 
[info] we are testing workhorse but mock test3 
[info] - should return mock for test3 
[info] Run completed in 2 seconds, 92 milliseconds. 

Pourquoi suis-je vois la déclaration d'impression came inside deux fois?

:: Modifier

Sur la base des conseils de Tavian ... c'est le code final qui a travaillé

class TestModule extends AbstractModule with ScalaModule with MockitoSugar { 
    override def configure() = { 
     val module = new MainModule() 
     val injector = Guice.createInjector(module) 
     val realobject = injector.getInstance(classOf[TestPartialMock]) 
     val x = spy(realobject) 
     when(x.test3()).thenReturn("I am mocked") 
     bind(classOf[TestPartialMock]).toInstance(x) 
    } 
} 
+1

Pour les espions Mockito, 'when (x.workHorse())' aura déjà appelé la vraie méthode 'workHorse()'. En fait, il n'y a pas besoin de '.thenCallRealMethod()' car c'est le comportement par défaut des espions. –

Répondre

2

Pour des espions, vous devez être prudent des expressions comme

when(x.workHorse()).thenCallRealMethod() 

parce x.workHorse() est vraiment invoqué dans cette expression! x ne « savent » pas que ce soit à l'intérieur d'un appel when(), comme l'expression est réduite en quelque chose comme ceci:

tmp1 = x.workHorse(); 
tmp2 = when(tmp1); 
tmp3 = tmp2.thenCallRealMethod(); 

Au lieu de cela, vous pouvez écrire

doCallRealMethod().when(x).workHorse() 

qui supprimera l'invocation du réelle workHorse() mise en œuvre.

Mais, vous n'avez pas besoin de faire cela pour cet exemple — L'appel de méthodes réelles est le comportement par défaut des espions.

+0

J'ai essayé votre suggestion. J'ai édité mon post ci-dessus avec le nouveau code. Mais encore, je vois deux invocations. –

+0

Mais vous n'avez pas pris ma suggestion ('doCallRealMethod(). Quand (x) .workHorse()') –

+0

oui ça marche !!!!! –

-1

Comme vous l'avez mentionné dans le titre de la question, vous avez une combinaison de 3 technologies. En fait 4 technologies, y compris l'outil de construction qui est utilisé pour exécuter le test. Vous pouvez isoler le problème par

1) Retirer Guice et instancier tout directement

2) Code Exécuter comme une simple application au lieu de courir comme un test par SBT/gradle/Maven.

Il est également judicieux d'imprimer la trace de pile avec un message came inside pour trouver un appelant.

+0

Tout fonctionne avec Guice est supprimé. tout le point de la tête est que je veux le faire avec Guice. C'est le noeud du problème. Sinon, c'est simple. –