Mocking an abstract class with a mocked constructor argument?

I would like to use Mockito for the unit test of an abstract class described in detail in this excellent answer.

The trick is that an abstract class has a dependency on a strategy that is introduced into its constructor. I created a strategy layout and I would like my mocking BaseClass instance to use the mocked strategy for my unit test.

Any suggestion on how I can connect this? I am not currently using the IoC framework, but am considering Spring. Perhaps this will be a trick?

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

Update :
According to the Mockito mailing list, there is currently no way to pass arguments to the layout constructor.

+6
source share
3 answers

I saw what was done using Mockito at the spring context level.

eg:

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

Hope this helps.

+4
source

In the end, I just used reflection to set a private field in my base class, for example:

 // 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 ... 

It will break if the name of the private field has ever changed, but commented on it, and I can live with it. This is a simple, one line of code, and I find it preferable to expose any setters or have an explicit subclass in my tests.

Edit: So this is not a single line of code, since my personal field should be "final", which requires an additional reflection code.

+4
source

You do not need to do anything special. Just make fun of the bean as usual:

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

It just works :)

-1
source

Source: https://habr.com/ru/post/913372/


All Articles