2012-04-16 7 views
6

Ich möchte Mockito zu Unit-Test eine abstrakte Klasse verwenden, wie in diesemVerspottung einer abstrakten Klasse mit einem gespotteten Konstruktorargument?

Der Trick ist great answer. detailliert, hat die abstrakte Klasse eine Abhängigkeit von einer Strategie, die in seinem Konstruktor injiziert wird. Ich habe ein Mock der Strategie erstellt und möchte, dass meine verspottete Instanz von BaseClass die verspottete Strategie für meinen Komponententest verwendet.

Irgendwelche Vorschläge, wie ich dies verdrahten kann? Ich verwende derzeit kein IoC-Framework, denke aber über Spring nach. Vielleicht würde es den Trick tun?

// abstract class to be tested w/ mock instance 
abstract BaseClass 
{ 
    // Strategy gets mocked too 
    protected BaseClass(Strategy strategy) 
    { 
     ... 
    } 
} 

aktualisieren:
Nach der Mockito Mailing-Liste gibt es zur Zeit keine Möglichkeit, Argumente an den Konstruktor eines Mock zu übergeben.

Antwort

4

Ich habe diese Art der Sache mit Mockito im Frühjahr Kontext Ebene gesehen.

zB:

<bean id="myStrategy" name="myStrategy" class="org.mockito.Mockito" factory-method="mock"> 
    <constructor-arg value="Strategy" /> 
</bean> 

Ich hoffe, das hilft.

-1

Sie müssen nichts Besonderes tun. Nur verspotten die Bohne wie normal:

Bean bean = mock(Bean.class); 
when(bean.process()).thenReturn(somethingThatShouldBeNamedVO); 

gerade arbeitet :)

+0

Danke, Jordanien! Unglücklicherweise glaube ich nicht, dass es für meinen Fall funktionieren wird, da ich ein spezifisches Spottverhalten in der Strategieklasse benötige, die in die Basis injiziert wird. Wenn ein Standard-Mock der Strategie verwendet wurde (der nur Null, 0 usw. zurückgibt), würde die Logik der gemeldeten Basisklasse brechen. Trotzdem danke! – HolySamosa

+0

Dies beantwortet die Frage nicht. –

4

landete ich nur mithilfe von Reflektion in meiner Basisklasse ein eigenes Feld setzen, etwa so:

// mock the strategy dependency 
Strategy strategyMock = mock(Strategy.class); 
when(....).thenReturn(...); 

// mock the abstract base class 
BaseClass baseMock = mock(BaseClass.class, CALLS_REAL_METHODS); 

// get the private streategy field 
Field strategyField = baseMock.getClass().getSuperclass().getDeclaredField("_privateStrategy"); 

// make remove final modifier and make field accessible 
Field modifiersField = Field.class.getDeclaredField("modifiers"); 
modifiersField.setAccessible(true); 
modifiersField.setInt(strategyField, strategyField.getModifiers() & ~Modifier.FINAL);   
strategyField.setAccessible(true); 

// set the strategy 
strategyField.set(baseMock, strategyMock); 

// do unit tests with baseMock 
... 

Es wäre break, wenn sich der Name des privaten Feldes jemals geändert hat, aber es kommentiert und damit kann ich leben. Es ist einfach, es ist eine Zeile Code, und ich finde, dass dies vorzuziehen ist, um irgendwelche Setter freizulegen oder in meinen Tests explizit Unterklassen zu bilden.

Edit: Es ist also nicht mehr eine Codezeile, da mein privates Feld "final" sein muss, was einen zusätzlichen Reflexionscode erfordert.

+1

Toller Beitrag! Sie können all dies mit einer Zeile machen, wenn Sie eine Spring-Abhängigkeit haben ;-). Habe diese Klasse gefunden, während ich in Spring's Schachtel mit Leckereien herumschnüffelte. 'org.springframework.test.util.ReflectionTestUtils.setField (baseMock," _privateStrategy ", strategyMock)' –

Verwandte Themen