2017-05-04 5 views
3

aufgerufen Ich habe das geschrieben folgenden Code in Scala, Guice, Mockito und ScalaTestScala Mockito Guice und Teil Mocking .... Methoden zweimal

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] 
    } 
} 

und ich habe Fälle Unit-Test geschrieben mit teilweise spöttisch

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) 
    } 
} 

Meine Tests sind erfolgreich und ich kann sehen, dass es die richtige Menge von Methoden verspottet und die tatsächliche Implementierung der richtigen Menge von Methoden aufruft. Aber wenn ich am Ausgang schauen sehe ich

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. 

Warum erhalte ich die print-Anweisung came inside zweimal?

bearbeiten ::

Basierend auf Anraten Tavian ... dies der letzte Code ist die

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

Für Mockito-Spione hat 'when (x.workHorse())' bereits die Methode 'workHorse()' aufgerufen. Tatsächlich ist '.thenCallRealMethod()' nicht erforderlich, da dies das Standardverhalten von Spionen ist. –

Antwort

2

Für Spione, müssen Sie

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

weil x.workHorse() wirklich in diesem Ausdruck aufgerufen wird, wie

vorsichtig von Ausdrücken sein! x nicht „wissen“, dass es in einem when() Anruf ist, wie der Ausdruck in etwa wie folgt verringert wird:

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

Stattdessen können Sie

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

schreiben, die den Aufruf der unterdrücken echte workHorse() Implementierung.

Aber, Sie müssen nichts davon für dieses Beispiel tun — aufrufen echte Methoden ist das Standardverhalten von Spionen.

+0

Ich habe deinen Vorschlag ausprobiert. Ich habe meinen Beitrag oben mit dem neuen Code bearbeitet. Aber ich sehe immer noch zwei Anrufungen. –

+0

Aber du hast meinen Vorschlag nicht angenommen ('doCallRealMethod(). When (x) .workHorse()') –

+0

ja es funktioniert !!!!! –

-1

arbeitete Wie Sie in der Frage Titel erwähnt, haben Sie eine Kombination von drei Technologien. Eigentlich 4 Technologien einschließlich Build-Tool, mit dem der Test durchgeführt wird. Sie können das Problem durch

1) Entfernen Sie Guice isolieren und alles instanziiert direkt

2) Run Code als eine einfache App statt als Test läuft von SBT/gradle/Maven.

Es ist auch sinnvoll, Stack-Trace zusammen mit einer came inside Nachricht zu drucken, um einen Anrufer zu finden.

+0

Alles, was mit Guice funktioniert, wird entfernt. der springende Punkt der thead ist, dass ich es mit Guice machen will. Das ist der Kern des Problems. Ansonsten ist es einfach. –