0

I am trying to write unit test for a method which uses an instance of cache as below

public void method(String abc) {
....
....
Cache cache = CacheFactory.getAnyInstance();
....
....
}

I know mocking is the way to resolve this dependency on cache. I am new to mocking and using mockito and not sure on how to pass the mocked cache to the method.

@Mock
Cache cache;

@Test
public void testMethod(){

   doReturn(cache).when(CacheFactory.getAnyInstance());
   method("abc");

}

The above is what I've tried and got the error.

Ruben
  • 3,986
  • 1
  • 21
  • 34
Anantha
  • 99
  • 4
  • 13
  • You cannot mock a static call with mockito. Have a look at [PowerMock](https://github.com/jayway/powermock/wiki/GettingStarted) – Ruben Oct 28 '15 at 15:24

2 Answers2

0

If you are testing some code path in your application component that calls CacheFactory.getAnyInstance() (such as method("abc")?), then you must ensure that the method gets a reference to the mock Cache another way since you cannot mock a static method on a class (i.e. getAnyInstance() on CacheFactory), at least not without some help from a framework like PowerMock. For example...

public class ExampleApplicationComponent {

  public void methodUnderTest(String value) {
    ...
    Cache hopefullyAMockCacheWhenTesting = CachFactory.getAnyInstance();
    ...
    // do something with the Cache...
  }
}

Of course, this will fail. So you need to restructure your code a bit...

public class ExampleApplicationComponent {

  public void methodUnderTest(String value) {
    ...
    Cache cache = fetchCache();
    ...
    // do something with the (mock) Cache...
  }

  Cache fetchCache() {
    return CacheFactory.getAnyInstance();
  }
}

Then in you test case in your test class...

public class ExampleApplicationComponentTest {

  @Mock
  private Cache mockCache;

  @Test
  public void methodUsesCacheProperly() {
    ExampleApplicationComponent applicationComponent = 
        new ExampleApplicationComponent() {
      Cache fetchCache() {
        return mockCache;
      }
    };

    applicationComponent.method("abc");

    // assert appropriate interactions were performed on mockCache
  }
}

So as you can see, you can override the fetchCache() method in your anonymous ExampleApplicationComponent subclass within you test case to return the mock Cache. Also note, the fetchCache() method was deliberately made "package-private" to limit it's accessibility to primarily the test class (since test classes usually and should reside in the same package as the class under test). This prevents the fetchCache method from escaping and becoming part of your API. While other classes in the same package can access the method of an instance of the ExampleApplicationComponent class, you at least retrain control over that usage (and of course there is not substitute for good documentation).

To see other examples of this in practice, have a look as Spring Data GemFire's CacheFactoryBeanTest class (for instance, and specifically), which does exactly what I described above using Mockito.

Hope this helps.

Cheers! -John

John Blum
  • 7,381
  • 1
  • 20
  • 30
  • thanks for the detailed explanation. Ideally when I am the owner of both the main class and the test class I do this modification. But in my scenario I am not the owner neither I have permission to modify the class as it is a part of production code. I have to totally handle it through tests only. Since this is unit test I am having issue. Integration and System tests are just fine to write without any of these problem. – Anantha Oct 28 '15 at 15:46
0

I was ble to do this with the help of PowerMockito below is the code

mockStatic(CacheFactory.class);
when(CacheFactory.getAnyInstance()).thenReturn(cache);

method("abc");

verifyStatic();
CacheFactory.getAnyInstance();
Anantha
  • 99
  • 4
  • 13