Monday 27 April 2015

Powermock

Powermock is a mocking framework that extends other mocking frame works like EasyMock and Mockito. Before discussing about Powermock let us briefly discuss about unit testing, mocking.

Unit Testing
Unit testing is a software testing method by which, we can test each part of the program separately. The goal of unit testing is to isolate each part of the program and show that the individual parts are correct.

What is mocking and why it is required?
Let’s consider following scenario.

There are 4 modules (Assume them like classes), module1, module2, module3, and module4 in an Application. Let us assume, you have a team of 4 members and assigned each module to every one. There is a dependency on module4 for all other three modules1, 2 and 3. To make the progress of Application faster, you assume that module4 will be implemented on time and started developing modules1,2, 3 and 4 parallel. Unfortunately Module 4 is not implemented on time, it may take another 2 months to finish, but all other modules 1 and 2 and 3 are finished and ready for testing. But you can’t test the complete functionality of modules 1, 2 and 3, since they are dependent on module4. All modules 1, 2 and 3 must wait until the module 4 finished, which is not feasible, here mocking came into picture. Mocking create simulated objects that mimic the behavior of real objects. You create a mock object for module4 (Assume that this functionality will be unit tested, after implementation) and test other modules 1, 2, and 3.

The idea of unit testing is that you can test your code without testing the dependencies and the code written by others. This test allows you to verify that the code being tested works, regardless of its dependencies. The idea is that if the code I write works as designed and my dependencies work as designed, then they should work together as designed. This is explained by following example in detail.

Step 1: Create new maven project, mockito_tutorial.


Select the check box “Create a new simple project (skip archetype selection).

Step 2: Open pom.xml, update dependency for mockito.

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>mockito_tutorial</groupId>
 <artifactId>mockito_tutorial</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <properties>
  <powermock.version>1.6.2</powermock.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.powermock</groupId>
   <artifactId>powermock-module-junit4</artifactId>
   <version>${powermock.version}</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.powermock</groupId>
   <artifactId>powermock-api-mockito</artifactId>
   <version>${powermock.version}</version>
   <scope>test</scope>
  </dependency>
 </dependencies>
</project>


Step 3: Create a class “ConfigService.java” inside the package com.src.configurations.
package com.src.configurations;

public class ConfigService {

 public boolean testConfigurations(){
  /**
   * Code is not implemented, may take 2 months to finish
   */
  return true;
 }
}


Step 4: Create a class Application.java inside the package com.src.application.
package com.src.application;

import com.src.configurations.ConfigService;

public class Application {

 public String runApplication(ConfigService service) {
  if (service.testConfigurations()) {
   return startApplication();
  } else {
   return haltApplication();
  }
 }

 private String startApplication() {
  return "Application started";
 }

 private String haltApplication() {
  return "Application halted";
 }
}


Step 5: Create a class “ApplicationTest.java” inside the package com.test.application.

package com.test.application;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.powermock.api.mockito.PowerMockito;

import com.src.application.Application;
import com.src.configurations.ConfigService;

@RunWith(MockitoJUnitRunner.class)
public class ApplicationTest {
 
 @Test
 public void testRunApplication1() {
  Application application = new Application();
  
  ConfigService service =  PowerMockito.mock(ConfigService.class);;
  PowerMockito.when(service.testConfigurations()).thenReturn(true);
  
  String status = application.runApplication(service);
  assertEquals(status, "Application started");
 }

 @Test
 public void testRunApplication2() {
  Application application = new Application();

  ConfigService service =  PowerMockito.mock(ConfigService.class);;
  PowerMockito.when(service.testConfigurations()).thenReturn(false);
  
  String status = application.runApplication(service);
  assertEquals(status, "Application halted");
 }
}
When a class is annotated with @RunWith or extends a class annotated with @RunWith, JUnit will invoke the class it references to run the tests in that class instead of the runner built into JUnit.

Since testConfigurations() is not implemented fully, we have to mock the testConfigurations() to finish the testing of Application class. We can do this with following statement.

PowerMockito.when(service.testConfigurations()).thenReturn(false);

When testConfigurations() is called, then it returns false, instead of original implementation.

Step 6: Right click on ApplicationTest.java, Run as junit test.
You will get junit output like following.

Final project structure looks like below.




No comments:

Post a Comment