Contents

Unit Test

Mock

Spy

Difference between Mock and Spy

Difference Between doReturn()/when and When/thenReturn() 

Ways to Initialize the Mocks

Why Mockito does not mock static methods

Mocking a Static Method of an external class

Mocking static void method call 

Mock private methods of a class under test

Invoking private methods from the unit test class

How to use Powermockito so that private void methods calls are skipped

Unit test a constructor and mock the private methods that the constructor calls

Mocking a constructor

Setting a value to private variable using Mockito

Verify

Argument Captor

Throwing an exception

Using matchers

Best Practices

Unit Test

Unit testing is to test methods of one class in isolation. But classes are not isolated. They may use methods from other classes. Those are often referred to as collaborators (external classes). This leads to two major problems:

  • External services might not simply work in a unit testing environment as they require database access or some other external systems.
  • Testing should be focused on the implementation of one class. If external classes are used directly, their behavior is influencing those tests. That is usually not wanted.

This is where we use Mockito and PowerMockito Frameworks.

What is a Mock?

Mockito mock() method is to create a mock (dummy) object of external classes in a JUnit test. When doing unit testing, we are only testing the functionality of the class. It should not be dependent to other classes. That’s why we mock the external classes, or other dependencies.

Two ways to create a Mock Object

  • ServiceUtil mServiceUtil = Mockito.mock(ServiceUtil.class);
  • @Mock ServiceUtil mServiceUtil;

What is a Spy?

A Mockito spy is a partial mock. We can mock a part of the object by stubbing few methods. Calling a method on a spy will invoke the actual method, unless we explicitly stub the method.

Two ways to spy an object

  • List<Productgroup> sListOfproductGroup = Mockito.spy(new ArrayList<Productgroup>());
  • @Spy  List<Productgroup> sListOfproductGroup = new ArrayList<Productgroup>();

Difference between Mock and Spy

Both can be used to mock methods.The difference is that in mock, we are creating a complete mock or fake object.While in spy, there is the real object and we just stub specific methods of it.

When using mock objects, the default behavior of the method when not stub is do nothing. If it’s a void method, then it will do nothing when you call the method or if it’s a method with a return then it may return null.

While in spy objects, since it is a real object, when you are not stubbing the method, then it will call the real method. If you want to mock, then you need to stub it.

Difference Between doReturn()/when and When/thenReturn()

  1.  doReturn()/when and when/thenReturn() are same for mocked objects. None of them call the actual method.
  2.  doReturn()/when and when/thenReturn() have different behavior for spied objects. doReturn()/when – it will not call real method on spied object.              when/thenReturn() – it will call real method on spied object.

Ways to Initialize the Mocks

  1.  Using Mockito.mock()

This is called One-by-one explicit mocking.

Ex:

mock

2) MockitoAnnotations initMocks()

We can initialize all mocks by calling initMocks() method of MockitoAnnotations.

Syntax: MockitoAnnotations.initMocks(this);

mock-ways2

3) Using MockitoJUnitRunner

Another way to initialize mocks is to use @RunWith(MockitoJUnitRunner.class) annotation at the test class level. It initializes mocks annotated with @Mock.

Here usage of MockitoAnnotations.initMocks(Object) is not needed. Mocks are initialized before each test method.

mock-ways3

4) Using MockitoRule

Another way of initializing the mocks is to use the MockitoRule class. It initializes mocks annotated with @Mock. Here usage of MockitoAnnotations.initMocks(Object) is also not necessary.

mock-ways4

5) Using PowerMockRunner

If we are using PowerMockito to mock static or final methods then we need to annotate the class with @RunWith(PowerMockRunner.class). This statement tells JUnit to execute the test using PowerMockRunner. We will use annotation @PrepareForTest which takes the class that needs to be mocked.

mock-ways5

Why Mockito does not mock static methods

The reason may be that mock object libraries typically create mocks by dynamically creating classes at runtime. This means they inherit from the class to mock (that’s what Mockito does). This approaches do not work for static members, since you can’t override them using inheritance.

Mocking a Static Method of an external class

We need to use the PowerMockito.mockStatic to enable static mocking for all static methods of a class. This makes it possible to stub them using the when-thenReturn syntax.

And we don’t use the default JUnit runner when we use PowerMock. PowerMock provides its own runner which we will need to use, specified with the @RunWith annotation. The other annotation we are using @PrepareForTest is used to identify all of the classes that PowerMock will be mocking.

Below steps in setting up a test that mocks a static call.

  • Use the Power Mock runner:

@RunWith(PowerMockRunner.class)

  • Declare the class that we’re mocking:

@PrepareForTest(TagUtil.class)

  • Tell PowerMock the name of the class that contains static methods:

PowerMockito.mockStatic(TagUtil.class);

  • Stub the static method and return a mock value.

when(TagUtil.getTagIds()).thenReturn(tagIds);

Ex:

//External class

Public class TagUtil {

Public static List<String> getTagIds() {

// some code here

}

}

Unit Test:

static-mock

Mocking static void method call

Use PowerMockito doNothing() to mock/stub the static void method calls.

Ex:

static-void-mock

 

Mocking private methods of a class under test

Spy the class with PowerMockito and use PowerMockito doReturn syntax to stub private method of a class.

Ex:

mock-private

Invoking private methods from the unit test class

Use org.powermock.reflect.Whitebox class InvokeMethod() to invoke the private method of a class under test.

Syntax:

Whitebox. invokeMethod(Object instance, String methodToExecute, Object… arguments);

Ex:

invoking-private

Skip private void method call using PowerMockito

Use doNothing() to skip the private method call.

private-method-skip

Unit test a constructor and mock the private methods that the constructor calls

Ex:

In the below ProductUtil class constructor a private method is getting called which I need to stub and return some mock object if the private method returns something or  donothing() if  it is a void private method.

mock-const-void

 

Junit :

@Test

Public void testProductUtilConstructor() throws Exception{

// with below statement private method call cannot not be stubbed, because the productDetail object is not created yet, and it can only be created after the Constructor is called.

PowerMockito.doReturn(propertyMap).when(productUtil, “getTechSpecValues“, Mockito.any(Product.class), Mockito.any(List.class));

// with below statement the call to private method cannot be stubbed

doNothing().when(ProductUtil, “getSubDetails“,Mockito.any(Product.class), Mockito.anyBoolean());

// we call the constructor only after all mocking is done.

productUtil = PowerMockito.spy(new ProductUtil (mProductDetail, BigInteger.ONE,

mTechSpecList, “US”, “en”,”aqType”,true));

}

Solution:

we should not mock a class under test. If the constructor calls a method then the actions of the method should be tested as part of testing the constructor. If the method does stuff that is outside the scope of unit testing, mock the classes that method is using to do the “stuff”.

Mocking a constructor

Mocking a class constructor which has no parameters.

To stub an external class constructor call use PowerMockito whenNew() method and use withNoArguments() method if the constructor has no parameters to pass.

Ex :

ProductTest mProductTest = mock(ProductTest.class);

PowerMockito.whenNew(ProductTest.class).withNoArguments().thenReturn(mProductTest);

Mocking a class constructor which has parameters in 2 ways.

  1. Use PowerMockito whenNew() method and withArguments(…)

ProductDetailSpec mSpecifications = mock(ProductDetailSpec.class);

PowerMockito.whenNew(ProductDetailSpec.class).withArguments(Mockito.any(Product.class),Mockito.any(BigInteger.class),Mockito.anyBoolean()).thenReturn(mSpecifications);

2. Use PowerMockito whenNew() method and withAnyArguments()

ProductTest mProductTest = mock(ProductTest.class);

PowerMockito.whenNew(ProductTest.class).withAnyArguments().thenReturn(mProductTest);

Setting a value to private variable in mockito

Use whitebox setInternalState method to set a value to a private variable.

Listoftechspecs sListoftechspecs = Mockito.spy(new Listoftechspecs());

Whitebox.setInternalState(sListoftechspecs, “techspec”, techSpecList);

Verify

Mockito Verify method is used to verify if a method call is happened or not.

Ex:

verify(mResolver, times(1)).adaptTo(eq(Session.class));

Argument Captor

Argument Captor is used along with verify to capture the arguments for the method call so that they can be asserted.

Throwing an exception

If the method returns a value the syntax would be:

Mockito.when(method).thenThrow(new Exception());

If the method returns void, the syntax is :

Mockito.dothrow(Exception.class).when(instance).method(parameter);

Using matchers

When we want to return a value independently of the parameters content, we can use Matchers.any(Object.class) (where Object may be any custom class we prefer, or if use one of the classical Java types we may use their own methods: anyString(), anyInt(), anyList() …).

Ex:

PowerMockito.whenNew(ProductDetailSpec.class).withArguments(Mockito.any(Product.class), Mockito.any(BigInteger.class), Mockito.anyBoolean()).thenReturn(mSpecifications);

when(mResolverFactory.getServiceResourceResolver(Mockito.anyMapOf(String.class, Object.class))).thenReturn(mResolver);

If we want to do something like mixing parameters whose content we don’t mind while other values may be important, we should combine Matchers.any(Object.class) and Matchers.eq(instance)

Ex:

when(mServiceProxy.getValues(anyString(), eq(“T”))).thenReturn(mClassKeywords);

when(mJcrManager.getNodePath(Mockito.any(Product.class),eq(“path”),eq(“/content/tets/”))).thenReturn(TEST_NODE_PATH);

Another useful method is Matchers.isA(class).

Best Practices

1.Naming conventions: To identify the objects, mocks can start with “m” and spy object with “s”.

Ex:

Product mProduct = mock (Product.class);

Product sProduct = spy (new Product());

2. Don’t mock your model

Simply use your model class over mocking it.

Use:

Product Product = new Product ();

Product.setId (“123”);

Instead Of:

Product mProduct = mock (Product.class);

When(mProduct.getId()).thenReturn(“123”);

3. If we are using the same mock in many tests, then put the mock creation into @Before method. We can create a “basic” mock in setup () and add more mocked behavior to it in the individual test cases. Setup () gets called before each test, so you get fresh objects in each test.

Ex: In below case salesChannels object is used in two test methods

best-practice

 

4. Use the correct assertion method.

Use assertTrue(class.somethod());

Instead of using assertEquals(true, class.someMethod());

5. Declare all the mock objects as private.

6. Do not print anything out in unit tests.

7. Create unit tests that target exceptions.