Not able to Unit test this class using mocking API - powermock

Its a legacy code which I am not able to unit test using Powermock. Kindly help me in unit test below class using Powermock or any other way if there is any:
ServiceAPI class has to be unit tested
public class ServiceAPI {
public String getServiceKey(String serviceNumber){
String jndiUrl = getServURL();
return jndiUrl;
}
public String getServURL(){
String url = ServiceLocator.getInstance().init();
return url;
}
}
Above class has dependency on below class which has to be mocked
public class ServiceLocator {
private static ServiceLocator serviceLocator = new ServiceLocator();
public static ServiceLocator getInstance(){
return serviceLocator;
}
public String init(){
return "Jndi Call has return fix name";
}
}
I have written below test
#RunWith(PowerMockRunner.class)
#PrepareForTest(ServiceLocator.class)
public class ServiceAPITest {
#Test
public void testGetServiceKey() {
ServiceLocator serviceLocator = PowerMockito.mock(ServiceLocator.class);
PowerMockito.mockStatic(ServiceLocator.class);
PowerMockito.when(ServiceLocator.getInstance()).thenReturn(serviceLocator);
PowerMockito.when(serviceLocator.init()).thenReturn("value");
ServiceAPI serviceAPI = new ServiceAPI();
serviceAPI.getServiceKey("20156");
}
}
Not getting o/p. Please help!

Related

PowerMock ExpectNew creating real objects instead of mocked Ones

public class PersistenceManager {
public boolean addUser(User user) {
UserPersistor userPersistor = new UserPersistor(user) {
#Override
void somemethod() {
// TODO Auto-generated method stub
}
};
userPersistor.addUser();
System.out.println("PersistenceManager added user ");
return true;
}
class User {
public String firstName;
public String lastName;
public User(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
}
}
abstract class UserPersistor {
public UserPersistor( ) {
}
public UserPersistor(User user) {
}
public void addUser() {
System.err.println("UserPersistor added user ");
}
abstract void somemethod();
}
}
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.expectNew;
import static org.powermock.api.easymock.PowerMock.expectLastCall;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest( PersistenceManager.class )
public class PersistenceManagerTest {
private User user = null;
#Before
public void before() throws Exception {
user = createMock(User.class);
UserPersistor userPersistor = createMock(UserPersistor.class);
userPersistor.addUser();
expectLastCall();
expectNew(UserPersistor.class, user).andReturn(userPersistor);
PowerMock.replayAll();
}
#Test
public void testaddUser() {
PersistenceManager tested = new PersistenceManager();
tested.addUser(user);
PowerMock.verifyAll();
}
}
Whats wrong with above code? I dont see mocked object for UserPersistor. Meaning, i dont want to see "UserPersistor added user " printed. It should not do anything. But it is printing it since real object of UserPersistor is created. I am facing this problem in my actual project, thought would simulate and try to solve in a much smaller context. But I am stumped.
That's because you are not expecting to instantiate UserPersistor but an anonymous inner class extending UserPersistor.
To do that you need to retrieve that class, mock it and expect it. PowerMock has a Whitebox class to do that. You are exposing the class implementation when using it. I would recommend that you refactor your code to inject the code instead. But if you really want to, you should write this:
#Before
public void before() throws Exception {
user = createMock(PersistenceManager.User.class);
Class<Object> clazz = Whitebox.getAnonymousInnerClassType(PersistenceManager.class, 1);
PersistenceManager.UserPersistor userPersistor = createMock(clazz);
userPersistor.addUser();
expectNew(clazz, user).andReturn(userPersistor);
PowerMock.replayAll();
}

how to instantiate objects inside the class to be tested is an abstract class in Junit testing?

I have a class below for which I want to write a unit test
abstract class ProductImpl{
#Inject DataServices ds; // using Guice
public Response parse(String key, Long value){
Response res = ds.getResponseObject(); // Response object is created using DataServices object
res.id = key;
res.code = value;
}
}
And I have a test as below
class ProductImplTest{
#InjectMocks ProductImpl impl;
Map<String, Long> map;
#Before
map.put("abc", 10L);
map.put("xyz", 11L);
}
#Test
public void test(){
for(String key: map.keySet()){
Response res = impl.parse(key, map.get(key));
// and check if fields of Response object are set correctly i.e res.id is abc and value is 10L
}
}
But when i debug the test and control goes to parse method , DataServices object ds is null. How to instantiate this object through test . I do not want to use mocking, I want real response objects to be created and test the values set in them.
You can use Mockito
#RunWith(MockitoJUnitRunner.class)
class ProductImplTest {
#Mock DataService dService;
#InjectMocks ProductImpl sut;
#Test
public void test() {
ResponseObject ro = new ResponseObject();
String string = "string";
Long longVal = Long.valueOf(123);
sut.parse("string", longVal);
verify(dService).getResponseObject();
assertThat(ro.getId()).isEqualTo("string");
// you should use setters (ie setId()), then you can mock the ResponseObject and use
// verify(ro).setId("string");
}
}
EDIT:
With ResponseObject being an abstract class or preferably an interface, you'd have
interface ResponseObject {
void setId(String id);
String getId();
// same for code
}
and in your test
#Test public void test() {
ResponseObject ro = mock(ResponseObject.class);
// ... same as above, but
verify(dService).getResponseObject();
verify(ro).setId("string"); // no need to test getId for a mock
}
Try with constructor injection:
class ProductImpl{
DataServices ds;
#Inject
public ProductImpl(DataServices ds) {
this.ds = ds;
}
}

Junit Test (Mockito, PowerMock) a class with void method and private value

some sample code like:
(I just added some more details)
public class A {
#Autowired
private Data data;
#RequestMapping(value="/Boo", method = RequestMethod.GET)
public void Boo(){
data.someMethod();
}
}
I want to test the someMethod() is run or not.
I have tried #First answer but got some error message like below:
java.lang.AbstractMethodError: org.powermock.api.mockito.internal.exceptions.StackTraceCleanerProvider$1.isIn(Ljava/lang/StackTraceElement;)Z
at org.mockito.internal.exceptions.stacktrace.StackTraceFilter.filter(StackTraceFilter.java:33)
at org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter.filter(ConditionalStackTraceFilter.java:23)
at org.mockito.exceptions.base.MockitoException.filterStackTrace(MockitoException.java:44)
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#InjectMocks
private A a;
#Spy
private Data data;
#Test
public void test() {
// execute
this.a.Boo();
// verify
Mockito.verify(this.data).someMethod();
}
}

Mocking an injected object in a method return and UnsupportedOperationException method

I have a class that returns an injected object using Mockito. Everytime I test it, it returns a bull. How would I properly test it to return the correct object?
My class to test:
#Component
public class CarImpl {
#Inject
private Engine v6EngineImpl;
public Engine getEngine() {
return v6EngineImpl;
}
public Exhaust getExhaust() {
throw new UnsupportedOperationException("unsupported");
}
}
Tests:
#RunWith(MockitoJUnitRunner.class)
public class CarTest {
#InjectMocks
private CarImpl carImpl;
#Mock
private Engine v6EngineImpl;
#Test
public void testGetEngine(){
Engine v6EngineImpl = mock(V6EngineImpl.class);
Engine engine = carImpl.getEngine();
// always returns a bull no matter what, how to mock inject.
//return object correctly?
Assert.assertNotNull(engine);
}
#Test
public void testGetExhaust() {
// how to test thrown exception?
}
}
Thanks, I am not too familiar thanks
Try this:
#RunWith(MockitoJUnitRunner.class)
public class CarTest {
#InjectMocks
private CarImpl carImpl;
#Mock
private Engine v6EngineImpl;
#Test
public void testGetEngine(){
Engine engine = carImpl.getEngine();
//engine is the mock injected to CarImpl
Assert.assertNotNull(engine);
Assert.assertSame(engine,v6EngineImpl);
}
#Test(expected=UnsupportedOperationException.class)
public void testGetExhaust() {
carImpl.getExhaust();
}
}

How to write JUnit Test case

I am learning Junit testing on spring boot Application. my account controller method is depend on service class method. For that I used Mockito. I tried simple But here I am not getting how to write test case for following method? How I can use mockito.
can any one please help me for writing this test case?
AccountController
#RestController
#RequestMapping("/spacestudy/$ {InstituteIdentifier}/admin/account")
public class AccountController {
#Autowired
AccountService accService;
#GetMapping("/findAccountData")
public ResponseEntity<List<Tuple>> populateGridViews(#RequestParam(value="sClientAcctId",required=false) String sClientAcctId,
#RequestParam(value="sAcctDesc",required=false) String sAcctDesc,
#RequestParam(value="sInvestigatorName",required=false)String sInvestigatorName,
#RequestParam(value="sClientDeptId",required=false) String sClientDeptId) throws Exception {
return ResponseEntity.ok(accService.populateGridViews(sClientAcctId, sAcctDesc,sInvestigatorName,sClientDeptId));
}
}
AccountService
public List<Tuple> populateGridViews(String sClientAcctId, String sAcctDesc, String sInvestigatorName,
String sClientDeptId)throws Exception{
QAccount account = QAccount.account;
QDepartment department = QDepartment.department;
QAccountCPCMapping accountCPCMapping = QAccountCPCMapping.accountCPCMapping;
QInvestigator investigator = QInvestigator.investigator;
JPAQuery<Tuple> query = new JPAQuery<Tuple>(em);
query.select(Projections.bean(Account.class, account.sClientAcctId, account.sAcctDesc, account.sLocation,
Projections.bean(Department.class, department.sDeptName, department.sClientDeptId).as("department"),
Projections.bean(Investigator.class, investigator.sInvestigatorName).as("investigator"),
Projections.bean(AccountCPCMapping.class, accountCPCMapping.sCCPCode).as("accountCPC"))).from(account)
.innerJoin(account.department, department).innerJoin(account.accountCPC, accountCPCMapping)
.innerJoin(account.investigator, investigator);
if (StringUtils.isNotEmpty(sClientAcctId)) {
query.where(account.sClientAcctId.equalsIgnoreCase(sClientAcctId));
}
// code.......
return query.fetch();
}
AccountControllerTest
#RunWith(SpringRunner.class)
public class TestAccountController {
private MockMvc mockMvc;
#Mock
private AccountService accountService;
#InjectMocks
private AccountController accountController;
#Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(accountController).build();
}
#Test
public void populateGridViewsTest() throws Exception {
//????
//????
}
}
It will be something like this:
#RunWith(SpringRunner.class)
public class TestAccountController {
private MockMvc mockMvc;
#Mock
private AccountService accountService;
#InjectMocks
private AccountController accountController;
#Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(accountController).build();
}
#Test
public void populateGridViewsTest() throws Exception {
when(accountService.populateGridViews("foo","bar")).thenReturn(Arrays.asList(new Tuple("bazz"));
mockMvc.perform(get("/spacestudy/STACKOVERFLOW/admin/account/foo/bar"))
.andExpect(status().isOk())
.andExpect(jsonPath("someField").value("bazz"));
}
}
So basically you are replacing your service with mock and saying what it should return. In your particular case I don't see any reasons for unit testing this class, since it doesn't have any logic inside. But if you would have something like:
#GetMapping("/findAccountData")
public ResponseEntity<List<Tuple>> populateGridViews(...) throws Exception {
List<Tuple> result = accService.populateGridViews(...);
if(result==null){
return ResponseEntity.notFound();
}
return ResponseEntity.ok(result);
}
Then it would make more sense to test this class e.g.
1st test - mock your accService to return null and verify that response status is 404
2nd test - mock your accService to return not null and verify that response status is 200