Question

I know that if I need to mock a static method, this indicates that my design has some issue, but in my case this does not seem to be a design issue.

BundleContext bundleContext = FrameworkUtil.getBundle(ConfigService.class).getBundleContext();

Here FrameworkUtil is a class present in an api jar. Using it in code cant be a design issue.

my problem here is while running this line

FrameworkUtil.getBundle(ConfigService.class); 

returns null So my question, is there any way by which I can replace that null at runtime I am using Mockito framewrok and my project does not allow me to use powermock.

if I use

doReturn(bundle).when(FrameworkUtil.class)

in this way getBundle method is not visible since its a static method.

Was it helpful?

Solution

You are correct that is not a design issue on your part. Without PowerMock, your options become a bit murkier, though.

I would suggest creating a non-static wrapper for the FrameworkUtil class that you can inject and mock.

Update: (David Wallace)

So you add a new class to your application, something like this

public class UtilWrapper {
    public Bundle getBundle(Class<?> theClass) {
        return FrameworkUtil.getBundle(theClass);
    }
}

This class is so simple that you don't need to unit test it. As a general principle, you should only EVER write unit tests for methods that have some kind of logic to them - branching, looping or exception handling. One-liners should NOT be unit tested.

Now, within your application code, add a field of type UtilWrapper, and a setter for it, to every class that currently calls FrameworkUtil.getBundle. Add this line to the construtor of each such class

utilWrapper = new UtilWrapper();

And replace every call to FrameworkUtil.getBundle with utilWrapper.getBundle.

Now in your test, you make a mock UtilWrapper and stub it to return whatever Bundle you like.

when(mockUtilWrapper.getBundle(ConfigService.class)).thenReturn(someBundleYouMade);

and for the class that you're testing, call setUtilWrapper(mockUtilWrapper) or whatever. You don't need this last step if you're using @InjectMocks.

Now your test should all hang together, but using your mocked UtilWrapper instead of the one that relies on FrameworkUtil.

OTHER TIPS

unit test

package x;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

public class GunTest {

  @Before
  public void setUp() throws Exception {
  }

  @Test
  public void testFireTrue() {
    final Gun unit = Mockito.spy(new Gun());
    Mockito.doReturn(5).when(unit).getCount();
    assertTrue(unit.fire2());
  }

  @Test
  public void testFireFalse() {
    final Gun unit = Mockito.spy(new Gun());
    Mockito.doReturn(15).when(unit).getCount();
    assertFalse(unit.fire2());
  }

}

the unit: fire calls the static method directly, fire2 factors out the static call to a protected method:

package x;

public class Gun {

  public boolean fire() {
    if (StaticClass.getCount() > 10) {
      return false;
    }
    else {
      return true;
    }
  }

  public boolean fire2() {
    if (getCount() > 10) {
      return false;
    }
    else {
      return true;
    }
  }

  protected int getCount() {
    return StaticClass.getCount();
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top