Testing Interface methods using Mockito

how to mock interface using mockito example
mockito mock interface
mockito tutorial
mockito mock method
how to mock save method in mockito
mockito verify method called with arguments
mockito call real method with parameter
mockito spy interface

I am writing a JUnit test case for a method which internally invokes another method through interface. I am using Mockito to mock the interface but for some reason it gives me NPE. I debugged through but wasn't able to get any clue to fix it. getAllVendors() method throws exception which comes through an Interface.

MUT

public void prepare() throws AccountServiceException, ManagerException {
vendors = getVendorManager().getAllVendors();

microsites = new ArrayList<VendorMicrositeTO>();
microsites.add( new VendorMicrositeTO( "http://www.docusign.com", "docuSign" ) );

clientUser = createClientUserObject();

}

JUnit

@Test
public void testPrepare() throws Exception {
    AccountAction accountAction = new AccountAction();
    Map<String, Object> actionMap = new HashMap<>();
    actionMap.put("application", "ESignatureIntegrationAction");

    ActionContext.setContext(new ActionContext(actionMap));
    String beanName = Constants.VENDOR_MANAGER_SPRING_BEAN;
    PowerMockito.mockStatic(AppContext.class);
    PowerMockito.when(AppContext.containsBean( beanName )).thenReturn( true );

    IVendorDto iVendorDto = new VendorDto();
    iVendorDto.setActive(true);
    iVendorDto.setCreatedBy("9/15/2016");
    iVendorDto.setName("CorpESignClientUser");
    iVendorDto.setCreatedBy("SYSTEM");

    List<IVendorDto> vendorList = new ArrayList<>();
    vendorList.add(iVendorDto);

    IVendorManager iManager = Mockito.mock((IVendorManager.class));
    Mockito.when(iManager.getAllVendors()).thenReturn(vendorList);

    accountAction.setVendors(vendorList);
    accountAction.prepare();
}

Stack trace

java.lang.NullPointerException
at com.mercuryinsurance.esignature.ui.webapp.action.AccountAction.prepare(AccountAction.java:65)
at test.com.mercuryinsurance.esignature.ui.webapp.action.TestAccountAction.testPrepare(TestAccountAction.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Thanks, in advance

Seems you forgot to add a line in your test like:

accountAction.setVendorManager(iManager);

A Unit Testing Practitioner's Guide to Everyday Mockito, With Mockito, you create a mock, tell Mockito what to do when specific methods are called on it, and then use the mock instance in your test instead of the real thing. After the test, you can query the mock to see what specific methods were called or check the side effects in the form of changed state. Methods of Mockito. The Mockito framework provides a variety of methods such as mock(), verify(), when(), etc., used to test Java applications. Using these predefined methods makes testing very easy. The brief description of the Mockito methods are given below: Mockito mock() method. It is used to create mock objects of a given class or interface.

Your problem is basically that you wrote code that is hard to test. First, to learn how to improve your skills in that area, start here and spent some time watching videos. No Blockbusters, but still worth your time.

The key point you will learn there: you have to be careful where the objects your code is using is coming from. Meaning: maybe your code shouldn't call getVendorManager() ... but use some injected object of that class instead? Because then you can mock that easily.

Unit tests with Mockito - Tutorial, A mock object is a dummy implementation for an interface or a class in which you define the output of certain method calls. Mock objects are� The void method that you want to test could either be calling other methods to get things done, processing the input parameters, or maybe generating some values or all of it. With Mockito, you can

So yeah, I have been tackling a very similar issue.

GhosCat this is not a bad coding practice, this usecase is a logical outcome of the application of the SOLID principles within an IoT based application. If you decouple the layers of your application using interfaces and are testing an innner layer you are bound to come across testing an interface whose implementations have more interface dependencies.

You can achieve this goal using two testing angles combined

  1. Use the Parameterized JUnit runner to launch the one set of unit tests for all of the implementations.
  2. Then internally during each run initialize the mocked dependencies using Mockito

For more information on Parameterized testing (that's where i originally found it) be sure to visit this post. The manual initialization of mockito was something i found here.

All and all the resulting code looks like this:

 @RunWith(Parameterized.class)
 public class YourInterfaceTest {

   @Mock
   private ImplementationDependency sneakyBreakyNpeAvoided;

   @InjectMocks
   private YourInterfaceToTest iface;

   // constructor is used by the Parameterized runner to provide impelementations
   public YourInterfaceTest (YourInterfaceToTest ifaceToTest) {
       this.iface = ifaceToTest;
   }

   // this method is called always before running tests so a good time to inject anything
   @Before
   public void init() {
      MockitoAnnotations.initMocks(this);
      Mockito.when(sneakyBreakyNpeAvoided.returnTrue()).thenReturn(true);
   }

   @Test(expected = IllegalArgumentException.class)
   public void doSomething_nullParameter_throwsIllegalArgumentException() {
      Assert.fail(); // tests here :)
   }

   @Parameterized.Parameters
   public static Collection<YourInterfaceToTest > provideImplementations() {
      // change to Arrays.asList when multiple implementations are available
      return Collections.singletonList(new YourInterfaceImpl());
   }
}

Hope I understood the OP's issue well.

Mockito - Extra Interfaces with Annotations and Static Methods, How on earth can we test it? In the majority of testing frameworks you can't do such class casts on mocks since they are built with the CGLIB� If you want to test serviceImpl you will need to mock in this way: @Mock private OrderIF order; @InjectMocks private Service reqService = new ServiceImpl(); To make it work you either need to use runner or MockitoAnnotations.initMocks(this); in @Before method.

Allow spying on interfaces so that it is convenient to work with Java 8 , While Mockito supports and stubs by default the default methods in methods on a mocked interface the tests should not fail or should not be� Mocking in unit testing is extensively used in Enterprise Application Development with Spring. By using Mockito, you can replace the @Autowired components in the class you want to test with mock objects. You will be unit testing controllers by injecting mock services.

Mockito's Mock Methods, As with other articles focused on the Mockito framework (like Mockito Verify TestRule interface, called ExpectedException, and include it in a test class: This rule will be used to handle exceptions thrown from test methods. There are several custom settings that are supported by methods of the MockSettings interface, such as registering a listener for method invocations on the current mock with invocationListeners, configuring serialization with serializable, specifying the instance to spy on with spiedInstance, configuring Mockito to attempt to use a constructor when instantiating a mock with useConstructor, and some others.

Mockito.mock() vs @Mock vs @MockBean, Learn the differences between different types of Mocking with Mockito. The Mockito.mock() method allows us to create a mock object of a class or an interface. We can do this either by using the MockitoJUnitRunner to run the test or calling� One problem I do see, however, is that introducing a new non-default method to the interface will break this test, in fact the test won’t even compile. I would argue that this is a sign of tight coupling, and hence bad software design. One suggestion would be to use Mockito to mock the interface.

Comments
  • Sorry but there is no setter for IManager.
  • @Jaykumar: In the spirit of the solution, this is correct though. Somehow you need to supply the value that getVendorManager will provide, or it will happily return null.
  • I am getting vendorManager and while debugging it goes through getVendorManager but for some reason it doesn't go in to getAllVendors()
  • I will follow the guidelines, but what should I do now. I can't stop testing and I can't change the code either.
  • I guess then you get the person behind the other answer to give you a working solution ;-)
  • Correct and you are not that lucky person :)