2016-04-05 16 views
2

Ich benutze Mockito, um meinen Kotlin-Code zu testen. Es ist eine Web-App und ich benutze Frühling, um Werte in einige Felder zu injizieren.Kotlin Lazy Block nicht ausgeführt, wenn Mockito und InjectMocks verwenden

Zum Beispiel meiner Klasse Schnipsel sieht wie folgt aus etwas:

class MyComponent { 

    @Inject private lateinit var request: HttpServletRequest 
    @Inject private lateinit var database: Database 

diesen Test in meiner Einheit zu imitieren verwende ich die @Mock und @InjectMocks Anmerkungen von Mockito. So sieht mein Test in etwa so aus:

class MyComponentTest { 

    @Mock private lateinit var request: HttpServletRequest 
    @Mock private lateinit var database: Database 

    @InjectMocks private lateinit var sut: MyComponent 

    @Before 
    fun setup() { 
     MockitoAnnotations.initMocks(this) 
    } 

Was alles funktioniert. Allerdings habe ich auch einen faulen Initialisierungsbaustein in meiner Komponente wie dieses:

val user: User by lazy { 
    database.findUser() 
} 

fun getUsername(): String { 
    return user.name 
} 

Als mein Testanrufe myComponent.getUsername() Ich würde erwarten, database.findUser() genannt werden, da es user initialisiert, aber dies nicht geschieht.

Wenn ich einen Haltepunkt in den Lazy Block setze, wird er nie getroffen. Nun gehe ich davon aus, dass dies etwas damit zu tun hat, wie Mockito und @InjectMocksuser berühren müssen, aber ich weiß es nicht wirklich. Wenn ich manuell MyComponent konstruiere, dann wird der Lazy Block ausgeführt - aber das wird meine Mocks nicht injizieren.

Wie kann ich sicherstellen, dass der Lazy Block von meinem Test korrekt aufgerufen wird?

UPDATE: Nach einer Woche Abwesenheit, versucht, dies ohne Änderungen zu reproduzieren, und ich konnte nicht. Kann es nicht erklären.

+0

Es wäre hilfreich, wenn Sie eine [MCVE] (http://stackoverflow.com/help/mcve) bereitstellen könnten. Wie es jetzt ist, kann ich Ihren Code nicht kopieren und reproduzieren das Problem, das Sie sehen. – mfulton26

Antwort

1

Ich habe versucht, Ihr Problem zu reproduzieren und war nicht in der Lage, dies zu tun. Diese gist bietet ein funktionierendes Beispiel.

Allerdings würde ich empfehlen, die Art, wie Sie Tests schreiben zu wiederholen. Betrachten Sie folgendes Beispiel:

class MyComponentTest { 

    val request = mock<HttpServletRequest>() 
    val database = mock<Database>() 
    val sut = MyComponent(request, database) 

    @Test 
    fun username() { 
     Mockito.`when`(database.findUser()).thenReturn(User("test")) 

     val username = sut.getUsername() 

     MatcherAssert.assertThat(username, Matchers.equalTo("test")) 
    } 
} 

die meiner Meinung nach ist leichter zu verstehen als die in den genannten the gist.

Falls Sie interessiert sind, die mock Hilfsfunktion ist ein Motto:

inline fun <reified T : Any> mock() = Mockito.mock(T::class.java) 

Ein vollständiges aktualisierte Beispiel kann in diesen gist finden.

+0

Danke für den Vorschlag, Konstruktor-Injektion zu verwenden, ich mag das, weil es bedeutet, dass ich meine Late-Inits loswerden und Vals anstelle von Vars verwenden kann. Was das ursprüngliche Problem anbelangt, werde ich meine Frage mit einem MCVE aktualisieren, was allerdings merkwürdig ist. – Jumwah

+0

OK, ich kam nach einer Woche Urlaub zurück und versuchte mein Problem ohne Glück zu reproduzieren. Etwas sehr Seltsames passierte, aber mein ursprünglicher Code ohne Änderungen funktioniert jetzt. Danke für Ihre Bemühungen! – Jumwah

+0

Ich möchte erwähnen, dass der Inhalt, der in der Antwort erwähnt wurde, bereits in den späten Annotationsstil geändert wurde, der meiner Meinung nach klarer ist. – fangzhzh

Verwandte Themen