How to mock super class method using power mock. In CardRepo in am using superclass method to get jdbcTemplate but using power mock i am not able to mock super.method in CardRepo class. how to mock super.getJdbcTemplate() using power mock.
public abstract class AbstractRepository {
#Autowire
private static JdbcTemplate jdbcTemplate;
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
}
Class CardRepo extends AbstractRepository{
#Override
public List<Card> getCardList(CommonInputBean inputBean) {
List<Card> data=Collections.emptyList();
data = super.getJdbcTemplate().query(query.toString(), new BeanRowMapper<Card>(Card.class)); // how to mock
return data;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({ CardRepo.class})
class CardTest{
#Spy
private CardRepo cardRepository = new CardRepo();
#Test
public void getCardList() {
Method method = PowerMockito.method(AbstractRepository.class, "getJdbcTemplate");
PowerMockito.suppress(method);
Method methodFoo = PowerMockito.method(AbstractRepository.class, "getJdbcTemplate");
PowerMockito.replace(methodFoo).with(new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return jdbcTemplate;
}
});
PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(AbstractRepository.class));
CardRepositoryImpl child = PowerMockito.spy(new CardRepositoryImpl());
child.getJdbcTemplate();
PowerMockito.when(child.getJdbcTemplate()).thenReturn(jdbcTemplate);
List<Card> list = this.cardRepository.getCardList(inputBean);
}
}
Related
I am trying to write unit tests for a class having spring retry using the springRunner. But my #Autowired beans are null . Could you please let me know what I did wrong?
Below is my test class
#RunWith(SpringRunner.class)
#ContextConfiguration
public class DeltaHelperTest {
#Autowired
private DeltaHelper deltaHelper;
#Before
public void setUp() { System.setProperty("delta.process.retries", "2"); }
#After
public void validate() { validateMockitoUsage(); }
#Test
public void retriesAfterOneFailAndThenPass() throws Exception {
when(deltaHelper.restService.call(any(), any())).thenThrow(new HttpException());
deltaHelper.process(any(),any());
verify(deltaHelper, times(2)).process(any(), any());
}
#Configuration
#EnableRetry
#EnableAspectJAutoProxy(proxyTargetClass=true)
#Import(MockitoSkipAutowireConfiguration.class)
public static class Application {
#Bean
public DeltaHelper deltaHelper() {
DeltaHelper deltaHelper = new DeltaHelper();
deltaHelper.myStorageService= myStorageService();
deltaHelper.restService = restService();
return deltaHelper;
}
#Bean
public MyStorageService myStorageService() {
return new MyStorageService();
}
#Bean
public MyRestService restService() {
return new MyRestService();
}
#Bean
public MyRepo myRepository() {
return mock(MyRepo.class);
}
}
#Configuration
public static class MockitoSkipAutowireConfiguration {
#Bean MockBeanFactory mockBeanFactory() {
return new MockBeanFactory();
}
private static class MockBeanFactory extends InstantiationAwareBeanPostProcessorAdapter {
#Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return !mockingDetails(bean).isMock();
}
}
}
}
Here test service is null on deltaHelper object .
MyRepo.class is mocked as it has some more #autowired bean reference
Attaching other classes here
#Component
public class DeltaHelper {
#Autowired
MyRestService restService;
#Autowired
MyStorageService myStorageService;
#NotNull
#Retryable(
value = Exception.class,
maxAttemptsExpression = "${delta.process.retries}"
)
public String process(String api, HttpEntity<?> entity) {
return restService.call(api, entity);
}
#Recover
public String recover(Exception e, String api, HttpEntity<?> entity) {
myStorageService.save(api);
return "recover";
}
}
#Service
public class MyStorageService {
#Autowired
MyRepo myRepo;
#Async
public MyEntity save(String api) {
return myRepo.save(new MyEntity(api, System.currentTimeMillis()));
}
}
public class MyRestService extends org.springframework.web.client.RestTemplate {
}
Thank you
Tried MockitoJUnitRunner, But found that #Retryable works only when running with Spring
I'm not sure why you are trying to test framework functionality such as retry. Generally, you can assume that framework components have been tested thoroughly by the framework authors.
Ignoring that, I can see at least two problems:
deltaHelper is not a mock, but your SUT, yet you try to set up method calls. If you mock your SUT, you are no longer testing your class, you are testing the mock. If you want your call to fail, don't mock the call, but mock its dependencies (e.g. MyRestService restService) and have calls on the dependency throw an exception.
You pass ArgumentMatchers.any() in your real method call (the "act" part), but any() unconditionally returns null (not some magic object). If you want to act on your SUT, you must pass real values. any is for setting up mocks or verifying calls on mocks.
For completeness' sake, here's the source of any():
public static <T> T any() {
reportMatcher(Any.ANY);
return null;
}
I have the below flow
#InjectMocks private ClassToTest classToTest;
#Mock private ClassToInject classToInject;
#Before
public void setup() {
initMocks(this);
}
#Test
public void test() {
Classx mockClassObj = Mockito.mock(Classx.class);
when(classToInject.publicMethod1(mockClassObj)).thenReturn(1000);
classToTest.publicMethod();
}
I want to test public method of classToTest. Now this method makes call to a private method, which I am not mocking. Inside this private method another public method is called, which I want to mock publicMethod1. Instead of the private method making use of value 1000 it is behaving as if the publicMethod1 was not mocked and I get NPE inside the flow of the method somewhere. I tried using #Spy with classToTest and also I am using init.mocks/#RunWith but it fails.
In short it is something like
ClassToTest. publicMethod --> ClassToTest.privateMethod(not mocking) --> ClassToInject.publicMethod1(want to mock)
The class looks like below
class ClassToTest {
#Inject ClassToInject classToInject;
public publicMethod() {
privateMethod();
}
private privateMethod() {
int x = classToInject.publicMethod1();
// use the return value
// throw exception
}
You mock classToInject.publicMethod1(mockClassObj) not classToInject.publicMethod1().
But your code invoked classToInject.publicMethod1();
int x = classToInject.publicMethod1(); // you invoked no parameter method
Check method which you want to invoke.
If You want to invoke classToInject.publicMethod1(), reference this code
#RunWith(MockitoJUnitRunner.class)
public class MockedTest {
#InjectMocks
private ClassToTest classToTest;
#Mock
private ClassToInject classToInject;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
Mockito.when(classToInject.publicMethod1())
.thenReturn(1000);
classToTest.publicMethod();
}
}
class ClassToTest{
ClassToInject classToInject;
public void publicMethod() {
privateMethod();
}
private int privateMethod() {
int x = classToInject.publicMethod1();
throw new NullPointerException(String.valueOf(x));
}
}
class ClassToInject{
public int publicMethod1() {
return 0;
}
}
The result is 1000 success
java.lang.NullPointerException: 1000
I am trying to call the real method in my testing class.
there are two methods one is public void m2() and another private void m3() in mapper class.
but here only private method gets execute and public method doesn't gets call.
Sample code is like.
public class Service {
#Autowired
Mapper mapper;
public void m1(String s){
System.out.println(s);
mapper.m1(s);
}
}
public class Mapper {
public String m1(String s){
System.out.println("inside m1 method" +s);
m2();
m3();
return s;
}
public void m2(){
System.out.println("inside m2 public method");
}
private void m3(){
System.out.println("insid m3 private method");
}
}
#RunWith(MockitoJUnitRunner.class)
public class Testing {
#Mock
Mapper mapper;
#InjectMocks
Service service;
#Test
public void test(){
when(mapper.m1(Mockito.any(String.class))).thenCallRealMethod();
service.m1("Check");
}
/**
* #param m1
*/
}
Public method is not called because you don't instruct mock to do so.
Private method is called because mockito doesn't affect private methods (You have to summon dark magic of PowerMock to do so).
I want to test a method which creates an object of another class using it's parameterized constructor. Even though I've mocked the constructor of MyClass, it makes the third party library which is in constructor implementation and results in the error. I'm using Mockito/PowerMockito.
public class MyClass{
private MyObj obj;
MyClass (String profile)
{
//some 3rd party library call
obj = thridPartyLib.someMethod(profile);
}
public String someMethod(){
return obj.someExternalCall();
}
}
Class which I want to test
public class ClassTobeTested{
public void execute(){
//some code
// ......
MyClass myClass = new MyClass(profile);
myclass.someMethod();
}
}
What I tried so far - classUnderTest.execute() ends up calling the thridPartyLib.someMethod(profile); which is part of MyClass constructor.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = new ClassTobeTested();
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute(){
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
Your code will work only if you are working with a spy or mock of classUnderTest. Try this. This should work
#RunWith(PowerMockRunner.class)
#PrepareForTest( {MyClass.class, ClassTobeTested.class })
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = spy(new ClassTobeTested());
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute() throws Exception {
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
The pain might suggest another approach. Consider injecting a Factory into ClassTobeTested which knows how to create an instance of MyObj. For example:
class MyObjFactory {
MyObj create(String profile) {
return new MyClass(profile);
}
}
then
public class ClassTobeTested {
private final MyObjFactory factory;
public ClassTobeTested(MyObjFactory factory) {
this.factory = factory;
}
public void execute(){
//some code
// ......
// MyClass myClass = new MyClass(profile);
MyClass myClass = factory.create(profile);
myclass.someMethod();
}
}
so the unit test becomes simpler with only having to mock the Factory and have it return a mocked MyClass instance. Then it's simple to verify myclass.someMethod() was invoked as expected.
Example of the problem:
class ToBeTested {
private MyResource myResource;
public toBeTested() {
this.myResource = getResource();
}
private MyResource getResource() {
//Creating My Resource using information form a DB
return new MyResource(...);
}
}
I would like to mock the getResource() so I would be able to provide a mock instance of MyResource. All the examples I found on how to mock a private method are based on first creating the ToBeTested instance and then replace the function but since it's being called from the constructor in my case it's to late.
Is it possible to mock the private function to all instances in advance of creating them?
Not directly but, you can suppress and then simulate with power mockito
#RunWith(PowerMockRunner.class)
#PrepareForTest(ToBeTested .class)
public class TestToBeTested{
#before
public void setup(){
suppress(method(ToBeTested.class, "getResource"));
}
#Test
public void testMethod(){
doAnswer(new Answer<Void>() {
#Override
public MyResource answer(InvocationOnMock invocation) throws Throwable {
return new MyResource();
}
}).when(ToBeTested.class, "getResource");
}
ToBeTested mock = mock(ToBeTested.class);
mock.myMethod();
//assert
}