Site icon NgDeveloper

How to test Controller using PowerMock in Spring Boot ?

Pre Requisite:

Make sure you have the below powermock maven dependencies.

Add the below dependencies to your pom.xml file:

<properties>
 <powermock-version>2.0.4</powermock-version>
</properties>

<dependency>
 <groupId>org.powermock</groupId>
 <artifactId>powermock-api-mockito2</artifactId>
 <version>${powermock-version}</version>
 <scope>test</scope>
</dependency>
<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-easymock</artifactId>
 <version>${powermock-version}</version>
 <scope>test</scope>
</dependency>
<dependency>
 <groupId>org.powermock</groupId>
 <artifactId>powermock-module-junit4-rule</artifactId>
 <version>${powermock-version}</version>
 <scope>test</scope>
</dependency>

Step 1: Add @RunWith at class level

@RunWith(PowerMockRunner.class)

your class with @RunWith annotation looks similar to this:

import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.assertEquals;

@RunWith(PowerMockRunner.class)
@PrepareForTest({CouponController.class})
public class CouponControllerTest {

}

Step 2: Add @InjectMocks annotation to your actual controller class

People who are familiar with Mockito, we use @Autowired directly to call the methods from our junits. Same way, if you are using Mockito then we need use @InjectMocks for our actual controller class where we are trying to write the test cases for the class.

@RunWith(PowerMockRunner.class)
public class CouponControllerTest {

 @InjectMocks
 CouponController couponController;

}

Step 3: Add @Mock annotation to all your dependent service classes.

@RunWith(PowerMockRunner.class)
public class CouponControllerTest {

 @InjectMocks
 CouponController couponController;

 @Mock
 CouponServiceImpl couponServiceImpl;
}

Add @Mock annotation for all your dependent classes like other service implementation and DAO’s.

Step 4: Write the Test cases

@InjectMocks
CouponController couponController;

// inside the test case method
CouponController couponControllerSpy = Mockito.spy(couponController);
@RunWith(PowerMockRunner.class)
public class CouponControllerTest {

 @InjectMocks
 CouponController couponController;

 @Mock
 CouponServiceImpl couponServiceImpl;

 @Before
 public void init() throws Exception {
   MockitoAnnotations.initMocks(this);
   List<Coupon> coupons = new ArrayList<>();
   Coupon coupon = new Coupon();
   coupon.setCouponId(1);
   coupon.setCouponTitle("10% OFF on Electronics");
   coupon.setCouponCode("SAVEJI10");
   coupons.add(coupon);
   when(couponServiceImpl.findAll()).thenReturn(coupons);
}

 @Test
 public void testCoupons(){
   Store store = new Store();
   store.setStoreId(3);
   CouponController couponControllerSpy = Mockito.spy(couponController);
   Map<Store, List<Coupons>> result = couponServiceImpl.getCoupons(store);
   assertEquals(result.size(), 1);
}
}

That’s it. Now you can run testCoupons method to test the getCoupons method of couponServiceImpl. Same way you can write n number of methods as per your need for all your possible test cases for both positive and negative.

Bonus

@Before can be effectively used with PowerMock.

When you want to test several methods and all needs some datasets in common then instead of repeating everything in all the test case methods, you can just do kind of prepopulation/preinitialize in @Before method only.

So that you do not want to repeat the same steps again and again.

Exit mobile version