How to mock Map with testng and powermockito - java

For personMap, I am setting the values with Powermockito;
But I am unable to get the values from map;
/**
*
*/
package mapmoocer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PersonStore {
Map<String, java.util.List<Person>> personMap = new HashMap<String, List<Person>>();
public void check() {
List<Person> list = personMap.get("RAM");
for(Person person : list) {
System.out.println(person);
}
}
public void hello() {
System.out.println("Hello");
}
}
Here, is the test class;
for test_check(), not able to cover for each block;
when(personMap.get("RAM")).thenReturn(value); always returning empty; even though I am setting the values for map;
/**
*
*/
package mapmoocer;
import static org.powermock.api.mockito.PowerMockito.when;
import java.util.ArrayList;
import java.util.Map;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.testng.PowerMockObjectFactory;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
public class PersonTest {
#InjectMocks
PersonStore personStore = new PersonStore();
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
#Mock
Map<String, java.util.List<Person>> personMap;
#BeforeClass
public void before(){
MockitoAnnotations.initMocks(this);
}
public void after() {
}
#Test
public void test_hello() {
personStore.hello();
}
#Test
public void test_check() {
Person person = new Person();
person.setEmail("aa");
java.util.List<Person> value = new ArrayList<Person>();
when(personMap.get("RAM")).thenReturn(value);
personStore.check();
}
}
Help me on this.

Why you want to mock a map? you can just create a new Map and assign it to your object. When we say Mock we Mock the action not the data.
We provide a mock is to make sure that the object we use will always provide a consistent value when we call one of its methods.
This will make us focus on the code we test, and don't need to worry about the method your code rely on will give you the wrong result.
So if you use a Map in your code, you just put the data in to the map, it's done. You don't need to mock it at all.

I am able to cover for-each snippet with the following code:
package mapmoocer;
import static org.powermock.api.mockito.PowerMockito.when;
import java.util.ArrayList;
import java.util.Map;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.testng.PowerMockObjectFactory;
import org.testng.Assert;
import org.testng.IObjectFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
public class PersonTest {
#InjectMocks
PersonStore personStore = new PersonStore();
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
#Mock
Map<String, java.util.List<Person>> personMap;
#BeforeClass
public void before(){
MockitoAnnotations.initMocks(this);
}
#AfterClass
public void after() {
}
#Test
public void test_hello() {
personStore.hello();
}
#Test(dataProvider="store")
public void test_check(Object data) {
java.util.List<Person> persons = (java.util.List<Person>)data;
when(personMap.get("RAM")).thenReturn(persons);
personStore.check();
}
public Object[][] store() {
Person person = new Person();
person.setEmail("aa");
person.setName("AA");
java.util.List<Person> value = new ArrayList<Person>();
value.add(person);
Object[][] result = {
{value}
};
return result;
}
}

Related

How Spring's Cacheable Annotation can work for class initailized through new Keyword. (In a Class Constructor, initialized through Bean)

In our service, we are initializing a bean (say "A") and that internally constructing a CacheableService Object by using - new CacheableService(). And as I know spring's #Cacheable annotations won't work on class method if the class is initialized using "new" Keyword.
Then what is an alternative or a way to cache method response?
Scenario :
<bean class="com.package.src.A"/>
public class A {
Map<String, CacheableService> map;
public CacheableService2() {
map = new HashedMap();
map.put("a", new CacheableService());
}
}
import org.springframework.cache.annotation.Cacheable;
public class CacheableService {
#Cacheable(value = "entityCount", key = "#criteria.toString()")
public int someEntityCount(final String criteria) {
System.out.println("Inside function : " + criteria);
return 5;
}
}
Here is a minimum example which demonstrates caching using Spring Boot. The code for the examples below can be found here.
Go to https://start.spring.io/ and create a new Spring Boot project. Make sure to include "Spring cache abstraction" which results in this entry being added to your pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
Add the #EnableCaching annotation to your application:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
#EnableCaching
#SpringBootApplication
public class CacheableApplication {
public static void main(String[] args) {
SpringApplication.run(CacheableApplication.class, args);
}
}
Your service:
package com.example;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
#Service
public class CacheableService {
#Cacheable(value = "entityCount")
public int someEntityCount(final String criteria) {
System.out.print(String.format("Inside function: %s", criteria));
return 5;
}
}
Class A:
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class A {
private CacheableService cacheableService;
public A(#Autowired CacheableService cacheableService) {
this.cacheableService = cacheableService;
}
public int getEntityCount(String criteria) {
return cacheableService.someEntityCount(criteria);
}
}
And then here is a test that demonstrates that the caching is working. As you can see in the test a.getEntityCount("foo") is being called twice, but in standard out we only see "Inside function: foo" being printed once. Therefore we have verified that the second call resulted in the cache being used to produce the result.
package com.example;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
#SpringBootTest
class CacheableTest {
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
#Autowired
private A a;
#BeforeEach
public void init() {
System.setOut(new PrintStream(outContent));
}
#Test
public void testCaching() {
a.getEntityCount("foo");
a.getEntityCount("foo");
assertEquals("Inside function: foo", outContent.toString());
}
}
EDIT:
If you want to move the cache outside of the Spring lifecycle and manually manage it then I would recommend using Caffeine. Here is the same example but now without any Spring involved.
Your service:
package com.example.withoutspring;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import java.util.concurrent.TimeUnit;
public class CaffeineCachingService {
private LoadingCache<String, Integer> entityCountCache = Caffeine.newBuilder()
.expireAfterAccess(5, TimeUnit.MINUTES)
.build(key -> someEntityCount(key));
public int cachedEntityCount(final String criteria) {
return entityCountCache.get(criteria);
}
private int someEntityCount(final String criteria) {
System.out.print(String.format("Inside function: %s", criteria));
return 5;
}
}
Class B:
package com.example.withoutspring;
public class B {
private CaffeineCachingService cacheableService;
public B() {
cacheableService = new CaffeineCachingService();
}
public int getEntityCount(String criteria) {
return cacheableService.cachedEntityCount(criteria);
}
}
And the same test but without Spring:
package com.example.withoutspring;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CaffeineCacheableTest {
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private B b = new B();
#BeforeEach
public void init() {
System.setOut(new PrintStream(outContent));
}
#Test
public void testCaching() {
b.getEntityCount("foo");
b.getEntityCount("foo");
assertEquals("Inside function: foo", outContent.toString());
}
}
Obviously you need to tune the cache to perform how you want it so probably evicting the cached values after 5 minutes is not what you want but if you visit the Caffeine Github page you will see a lot of detailed examples how to configure the cache to meet your use-case.
Hope this helps!

Getting Mockito error: "Wanted but not invoked... actually, there were zero interactions with this mock"

I'm getting the above error whilst running my unit test for a java class in an Android project (in Android Studio).
The class under test:
import android.content.Context;
import android.util.Log;
import **.CustomObject;
import java.util.concurrent.CountDownLatch;
import androidx.annotation.NonNull;
public class CustomClass {
private static final String string = "a";
private static CustomObject customObject = null;
private static CountDownLatch initializedLatch = new CountDownLatch(1);
#NonNull
public static CustomObject1 getCustomObject1() {
try {
initializedLatch.await();
assert customObject != null;
return customObject;
} catch (InterruptedException e) {
throw new RuntimeException(".");
}
}
public static void methodA(final Context context,
final String string1,
) throws exception {
initializedLatch.countDown();
}
public static void methodB(#NonNull final CustomObject customObjectInput) {
customObject = customObjectInput;
}
}
The test class:
import android.content.Context;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.concurrent.CountDownLatch;
import **.CustomObject;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;
#RunWith(MockitoJUnitRunner.class)
public class CustomClassTest{
#Mock
static CustomObject customObject;
#Mock
static Context context;
#Mock
CountDownLatch mCountDownLatch;
#Mock
CountDownLatch mInitializedLatch;
#InjectMocks
CustomClass customClass;
#Before
public void setUp() {
customObject = Mockito.spy(CustomObject.class);
context = Mockito.spy(Context.class);
}
#Test
public void customClassTest() {
doNothing().when(mInitializedLatch).countDown();
CustomClass.methodB(customObject);
try {
CustomClass.methodA(context, "");
} catch (Exception e) {
e.printStackTrace();
}
verify(mInitializedLatch).countDown();
try {
doNothing().when(mInitializedLatch).await();
} catch (InterruptedException e) {
e.printStackTrace();
}
Class.getCustomObject();
}
The specific message I'm getting when running customClassTest:
Wanted but not invoked:
mInitializedLatch.countDown();
-> at CustomClassTest.methodA(CustomClassTest.java:79)
Actually, there were zero interactions with this mock.
Wanted but not invoked:
mInitializedLatch.countDown();
-> at CustomClassTest.methodA(CustomClassTest.java:79)
Actually, there were zero interactions with this mock.
Running the debugger with break points at each of the relevant lines seems to suggest that the test runs fine (with all the variables being assigned correctly at the right points) until verify(mInitializedLatch).countDown();, when the message appears (and the code stops running).
Any help appreciated, thanks.
UPDATE #1:
Altered the code to remove static keyword:
import android.content.Context;
import android.util.Log;
import **.CustomObject;
import java.util.concurrent.CountDownLatch;
import androidx.annotation.NonNull;
public class CustomClass {
private final String string = "a";
private CustomObject customObject = null;
private CountDownLatch initializedLatch = new CountDownLatch(1);
#NonNull
public CustomObject1 getCustomObject1() {
try {
initializedLatch.await();
assert customObject != null;
return customObject;
} catch (InterruptedException e) {
throw new RuntimeException(".");
}
}
public void methodA(final Context context,
final String string1,
) throws exception {
initializedLatch.countDown();
}
public void methodB(#NonNull final CustomObject customObjectInput) {
customObject = customObjectInput;
}
}
import android.content.Context;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.concurrent.CountDownLatch;
import **.CustomObject;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;
#RunWith(MockitoJUnitRunner.class)
public class CustomClassTest{
#Mock
CustomObject customObject;
#Mock
Context context;
#Mock
CountDownLatch mCountDownLatch;
#Mock
CountDownLatch mInitializedLatch;
#InjectMocks
CustomClass customClass;
#Before
public void setUp() {
customObject = Mockito.spy(CustomObject.class);
context = Mockito.spy(Context.class);
}
#Test
public void customClassTest() {
doNothing().when(mInitializedLatch).countDown();
customClass.methodB(customObject);
try {
customClass.methodA(context, "");
} catch (Exception e) {
e.printStackTrace();
}
verify(mInitializedLatch).countDown();
try {
doNothing().when(mInitializedLatch).await();
} catch (InterruptedException e) {
e.printStackTrace();
}
customClass.getCustomObject();
}
Error messages now read:
error: non-static method methodA(Context,String) cannot be referenced from a static context
error: non-static method getCustomObject1() cannot be referenced from a static context
The second error message is displayed six times. It seems the code isn't compiling.
In CustomClass the CountDownLatch is declared as static field and it's initialized. If you debug your class you can see Mockito is not mocking/proxing this field. All the code interaction to initializedLatch object are not intercepted by Mockito proxy, so when you set-up your test by doNothing().when(mInitializedLatch).countDown(), actually you're not setting the field into customClass.So when you use verify(mInitializedLatch).countDown(), you're actually saying to Mockito that you expect one interaction with this mock, but no interactions are made due the reason above.
You are getting no invocations because the actual call is not made with your mocked mInitializedLatch object.
While mocking any object, you need to tell the compiler to use this mocked object instead of the one indeed present in your source implementation.
This can be achieved by making the object you are looking to test as an instance variable and passing the mocked object in the constructor.
Then the calls will be made from your mocked object and mockito will be able to track those.
Example:
// Source Code
public class CustomerClass {
private final CountDownLatch initializedLatch
public CustomerClass(CountDownLatch initializedLatch) {
this.initializedLatch = initializedLatch;
}
}
Now, use this instance variable in your code instead of the static variable you defined.
In test code, create constructor of CustomerClass by passing the mocked initializedLatch object and then it will work like charm.
If you are looking to initialize the value of initializedLatch there only. You can do the same by keeping a default constructor alongside the constructor I have defined above.
This default constructor can call the parameterized constructor.
public CustomerClass() {
this(new CountDownLatch(1));
}
Edit:
You also need to change your source implementation.
import android.content.Context;
import android.util.Log;
import **.CustomObject;
import java.util.concurrent.CountDownLatch;
import androidx.annotation.NonNull;
public class CustomClass {
private static final String string = "a";
private CustomObject customObject;
private CountDownLatch initializedLatch;
public CustomClass() {
this(new CountDownLatch(1), null);
}
public CustomClass(CountDownLatch initializedLatch, CustomObject customObject) {
this.initializedLatch = initializedLatch;
this.customObject = customObject;
}
#NonNull
public CustomObject1 getCustomObject1() {
try {
initializedLatch.await();
assert customObject != null;
return customObject;
} catch (InterruptedException e) {
throw new RuntimeException(".");
}
}
public void methodA(final Context context final String string1) throws Exception {
initializedLatch.countDown();
}
public void methodB(#NonNull final CustomObject customObjectInput) {
customObject = customObjectInput;
}
}
Now, above source implementation will use initializedLatch and customObject provided in the constructor.
Test code
import android.content.Context;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.concurrent.CountDownLatch;
import **.CustomObject;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;
#RunWith(MockitoJUnitRunner.class)
public class CustomClassTest{
#Mock
CustomObject customObject;
#Mock
Context context;
#Mock
CountDownLatch mInitializedLatch;
#InjectMocks
CustomClass customClass;
#Before
public void setUp() {
customClass = new CustomClass(mInitializedLatch, customObject);
}
#Test
public void customClassTest() {
doNothing().when(mInitializedLatch).countDown();
customClass.methodB(customObject);
try {
customClass.methodA(context, "");
} catch (Exception e) {
e.printStackTrace();
}
verify(mInitializedLatch).countDown();
try {
doNothing().when(mInitializedLatch).await();
} catch (InterruptedException e) {
e.printStackTrace();
}
customClass.getCustomObject();
}
Regarding the error you are getting, I don't think that's because of
the call you are making from the tests.

JUnit Testing FaceContext and Session Code

I am attempting to Junit test (IDE: Intellij) Method inside a class called "ManagementDashboardBean" called: (Method name): init()
The method contains FaceContext and Session. I tried the following: https://codenotfound.com/mockito-unit-testing-facescontext-powermock-junit.html
but am still running into issues. I am using Mockito and PowerMockito to help but cannot figure out my init() is saying Null Pointer Exception (NPE). Any guidance would be greatly appreciated. Thanks
P.S the end goal is to show proper test code coverage of this method.
public void init() {
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)context.getExternalContext().getSession(false);
userInfo = (UserSessionInfo)session.getAttribute(ConstantsUtil.USER_INFO);
startDt = FDUtil.toDate(FDUtil.toStartOfMonth(userInfo.getCurrentDateMillis()));
endDt = FDUtil.toDate(FDUtil.toEndOfMonth(userInfo.getCurrentDateMillis()));
autoCompleteDate = false;
}
Current JUnit Test
package view.managed.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import com.sun.jdi.connect.Connector;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({FacesContext.class})
public class ManagementDashboardBeanTest {
private ManagementDashboardBean someBean;
#Mock
private FacesContext facesContext;
#Mock
private ExternalContext externalContext;
#Before
public void setUp() throws Exception {
someBean = new ManagementDashboardBean();
//mock all static methods of FaceContext using PowerMockito
PowerMockito.mockStatic(FacesContext.class);
when(FacesContext.getCurrentInstance()).thenReturn(facesContext);
when(facesContext.getExternalContext()).thenReturn(externalContext);
}
#Test
public void testInitContext() {
//create Captor instances for the userInfo
// ArgumentCaptor<String> clientIdCapture = ArgumentCaptor.forClass(String.class);
// ArgumentCaptor<HttpSession> session = ArgumentCaptor.forClass(HttpSession.class);
// Run the method being tested
// someBean.init();
// verify(facesContext).addMessage(clientIdCapture.capture(), (FacesMessage) session.capture());
}
}
The actual .java source file starts with:
public class ManagementDashboardBean extends EntityManagerService implements Serializable {
private static final Logger LOG = LoggerFactory.getLogger(ManagementDashboardBean.class);
The right after is this, which confuses the hell out of me:
public ManagementDashboardBean() {
init();
}
What I have added so far:
import static org.junit.Assert.*;
import javax.faces.context.FacesContext;
import mil.af.fd.view.managed.services.EntityManagerService;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.powermock.core.classloader.annotations.PrepareForTest;
import java.io.Serializable;
#RunWith(MockitoJUnitRunner.class)
#PrepareForTest({FacesContext.class})
public class ManagementDashboardBeanTest {
private ManagementDashboardBean dashboard;
private Serializable serializableMock;
private EntityManagerService entityManagerServiceMock;
#BeforeClass
public static void before() {
System.out.println("Before Class");
}
#Before
public void setUp() throws Exception {
entityManagerServiceMock = Mockito.mock(EntityManagerService.class);
serializableMock = Mockito.mock(Serializable.class);
dashboard = new ManagementDashboardBean(serializableMock);
}
#Test
public void testInitContext() {
// dashboard.init();
System.out.println("Test 1");
}
}

trying to test spring caching . i need to test my #cacheble annatation on my repository

i am actually trying to test my caching mechanism . i am using caffine cache.
Test: i am calling caching method twice and expecting the same result for multiple method invocation. i.e When i cal method second time with same signature it shouldn't cal the method it should get the data from cache.
Problem: My code is actually invoking the method twice . i am mocking my repository. Please guide me, if anyone has solved this kind of problem.
my repo :
public class TemplateRepositoryOracle implements TemplateRepository
#Cacheable("Templates")
#Override
public Optional<NotificationTemplate> getNotificationTemplate(String eventTypeId, String destinationType, String destinationSubType) {}
Test:
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Ticker;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class TemplateRepositoyOracleTest {
interface TemplateRepository {
#Cacheable("Templates")
Optional<Template> getNotificationTemplate(String eventTypeId, String destinationType, String destinationSubType);
}
#Configuration
#ConfigurationProperties(prefix = "caching")
#Data
#Slf4j
static class CacheConfiguration {
#Data
public static class CacheSpec {
private Integer expireAfterWrite;
}
private Map<String, CacheSpec> specs;
#Bean
public CacheManager cacheManager(Ticker ticker) {
SimpleCacheManager manager = new SimpleCacheManager();
if (specs != null) {
List<CaffeineCache> caches =
specs.entrySet().stream()
.map(entry -> buildCache(entry.getKey(),
entry.getValue(),
ticker))
.collect(Collectors.toList());
manager.setCaches(caches);
}
return manager;
}
private CaffeineCache buildCache(String name, CacheSpec cacheSpec, Ticker ticker) {
log.info("Cache {} specified timeout of {} min", name, cacheSpec.getExpireAfterWrite());
final Caffeine<Object, Object> caffeineBuilder
= Caffeine.newBuilder()
.expireAfterWrite(cacheSpec.getExpireAfterWrite(), TimeUnit.MINUTES)
.ticker(ticker);
return new CaffeineCache(name, caffeineBuilder.build());
}
#Bean
public Ticker ticker() {
return Ticker.systemTicker();
}
#Bean
TemplateRepository myRepo() {
return Mockito.mock(TemplateRepository.class);
}
}
#Autowired
CacheManager manager;
#Autowired
TemplateRepository repo;
#Test
public void methodInvocationShouldBeCached() {
Optional<Template> third = Optional.of(new NotificationTemplate(UUID.randomUUID(),"Test",DestinationType.SMS,"test","test",Optional.empty(),Optional.empty()));
Optional<Template> fourth = Optional.of(new NotificationTemplate(UUID.randomUUID(),"Test2",DestinationType.SMS,"test2","test2",Optional.empty(),Optional.empty()));
// the mock to return *different* objects for the first and second call
Mockito.when(repo.getNotificationTemplate(Mockito.any(String.class),Mockito.any(String.class),Mockito.any(String.class))).thenReturn(third);
// First invocation returns object returned by the method
Object result = repo.getNotificationTemplate("1","1","1");
assertThat(result, is(third));
// Second invocation should return cached value, *not* second (as set up above)
result = repo.getNotificationTemplate("1","1","1");
assertThat(result, is(third));
// Verify repository method was invoked once
Mockito.verify(repo, Mockito.times(1)).getNotificationTemplate("1","1","1");
assertThat(manager.getCache("notificationTemplates").get(""), is(notNullValue()));
// Third invocation with different key is triggers the second invocation of the repo method
result = repo.getNotificationTemplate("2","2","2");
assertThat(result, is(fourth));
}
}
Property file:
caching:
specs:
Templates:
expireAfterWrite: 1440

Mocking final class with parameterized constructor

I have a final class as below
public class firstclass{
private String firstmethod(){
return new secondclass("params").somemethod();
}
}
public final class secondclass{
secondclass(String params){
//some code
}
public String somemethod(){
// some code
return somevariable";
}
}
I have to here test first class so I have mocked this as below
secondclass classMock = PowerMockito.mock(secondclass .class);
PowerMockito.whenNew(secondclass .class).withAnyArguments().thenReturn(classMock);
Mockito.doReturn("test").when(classMock).somemethod();
But it is not mocking as I expected can anyone help me?
The method firstclass.firstmethod() is private method. So try to test this method through public method in which it is getting called.
You can mock SecondClass and its final method using #RunWith(PowerMockRunner.class) and #PrepareForTest(SecondClass.class) annotations.
Please see below the working code:
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(SecondClass.class)
public class FirstClassTest{
#Before
public void init() {
}
#After
public void clear() {
}
#Test
public void testfirstmethod() throws Exception{
SecondClass classMock = PowerMockito.mock(SecondClass.class);
PowerMockito.whenNew(SecondClass.class).withAnyArguments().thenReturn(classMock);
Mockito.doReturn("test").when(classMock).somemethod();
new FirstClass().firstmethod();
}
}
Libraries used:

Categories

Resources