3

I am writing test cases for a legacy code which for some reason we dont want to change. The code is something like this

 public class ToBeTested{
    private static final String field1=SomeUtil.getProperty("somekey");        
    @AutoWired
    Someservice service;
 }

In my Junit I am using powermock with mockito and did something like this

public class myTestClass{
      @Mock
      SomeService service;
      @InjectMock
      ToBeTested tested;
}

However, InjectMocks fails to create the object for ToBeTested since the final fields are not provided

So I implemented a @BeforeClass and mocked the static method of SomeUtil. This works if i have only one test case. But for more than one test case, only one passes and others are failing with same error that

cannot instantiate @injectmocks field named you haven't provided the instance at field declaration

I have been able to resolve this by using something as below:

public class myTestClass{
          @Mock
          SomeService service;

          ToBeTested tested;

    @Before
    public void setup(){
        MockitoAnnotations.initMocks(this);
        mockStatic(SomeUtil.class);
        when(SomeUtil.getProperty(anyString())).thenReturn("test");
        toBeTested=new ToBeTested();    Whitebox.setInternalState(toBeTested,"someService",someService);
    }
    }

However am not a fan of using reflection in Junit which WhiteBox does internally. Is there a better way to do this?

Edit: Adding the snippet of code as suggested by Rann in comment

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeUtil.class)
public class myTestClass{
      @Mock
      SomeService service;
      @InjectMock
      ToBeTested tested;

    @BeforeClass
    public static void doBeforeClass(){
        mockStatic(SomeUtil.class);
        when(SomeUtil.getProperty(anyString())).thenReturn("test");
    }

    @Test
    public void test1(){
        tested.doSomethingFor1();
    }

    @Test
    public void test2(){
        tested.doSomethingFor2();
    }
}

test1 passes fine. for test2 i get an exception as

Caused by: org.mockito.exceptions.base.MockitoException: 
Cannot instantiate @InjectMocks field named 'tested' of type 'class com.xyz.ToBeTested'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null

    at org.powermock.api.extension.listener.AnnotationEnabler.injectSpiesAndInjectToSetters(AnnotationEnabler.java:72)
    at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:64)
    at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:82)
    ... 23 more
Caused by: java.lang.NullPointerException
    at com.xyz.SomeUtil.getProperty(SomeUtil.java:42)
varkashy
  • 374
  • 4
  • 18
  • I am assuming SomeUtils is a functional class. Have you considered working directly with it instead of trying to mock it? I assume there is a setProperty function which you can use in @BeforeClass in order to prepare SomeUtils for testing – Rann Lifshitz May 22 '18 at 02:00
  • @Rann Lifshitz Actually, I tried that, it worked for first test case but for second one it failed. It seems when it executes second test case it again creates the InjectMock instance and fails at that point,since the property elements are not there. Added a new edit part to reflect that code – varkashy May 22 '18 at 15:41
  • Also checked SomeUtil doesnt have a set property method, which i agree might be a bad design but this is legacy code and can't change the API on this one. – varkashy May 22 '18 at 15:48

0 Answers0