I have the class below:
Class Test{
private final Map<String, Map<BigInteger, String>> holder = new ConcurrentHashMap<>();
public boolean checkIfExists(String key){
return holder.containsKey(key);
}
}
I want to write test case for checkIfExists, How do I mock holder i.e Map in this scenario.
Better way for doing that, is creating a constructor having as an argument the holder attribute, then, you can mock it, or use an stub.
Class Test{
private final Map<String, Map<BigInteger, String>> holder;
public Test(final Map<String, Map<BigInteger, String>> holder){
this.holder = holder;
}
public boolean checkIfExists(String key){
return holder.containsKey(key);
}
}
Related
I have the following classes, which have quite similar method implementations. Only the classes' method inputs and outputs seem to be of different types. When I put it like this, it sounds like a case for inheritance, however, the fact that the inputs and outputs are different and are related to two lambdas, make me wonder if they should remain without any relationship, as one lambda cannot be thought of in place of another (To be a case for inheritance).
My first class looks like the following.
public class JobPersistenceManager {
private String jobIndexName;
private JobLambda JobLambda;
private MyDataPersistence myDataPersistence;
private DataProcessorUtils dataProcessorUtils;
private static final String JOB_ID = "jobId";
private static final String JOB_NAME = "jobName";
#Inject
public JobPersistenceManager(#Named("jobIndexName") String jobIndexName,
JobLambda JobLambda,
MyDataPersistence myDataPersistence) {
this.jobIndexName = jobIndexName;
this.JobLambda = JobLambda;
this.myDataPersistence = myDataPersistence;
createIndexIfNotExists(this.jobIndexName);
}
public SearchDocumentResult searchJob(MyJobInput myJobInput) throws IOException {
return myDataPersistence
.searchDocument(this.jobIndexName,
dataProcessorUtils.transformObjectDataPayloadToMap(myJobInput));
}
public MyJobOutput invokeCreateJobLambdaAndIndexData(final MyJobInput myJobInput)
throws IOException {
String personRequestPayload = dataProcessorUtils.transformObjectDataInputJson(myJobInput);
Map<String, String> createdJobOutput = this.JobLambda.invokeLambda(personRequestPayload);
this.indexCreatedJob(myJobInput, createdPersonOutput);
return MyJobOutput.builder().withJobID(createdJobOutput.get(JOB_ID))
.withJobName(createdJobOutput.get(JOB_NAME)).build();
}
public int indexCreatedJob(final MyJobInput myJobInput,
final Map<String, String> createdJobOutput) throws IOException {
myJobInput = modifyJobInput(myJobInput);
String documentToIndex = dataProcessorUtils.transformObjectDataInputJson(myJobInput);
return myDataPersistence.indexDocument(this.jobIndexName, documentToIndex);
}
private void createIndexIfNotExists(final String indexName) {
if (!myDataPersistence.doesIndexExist(indexName)) {
myDataPersistence.createIndex(CreateIndexInput.builder().indexName(indexName).build());
}
}
}
My second class looks like the following.
public class EmployeePersistenceManager {
private EmployeeLambda employeeLambda;
private MyTestDataPersistence myTestDataPersistence;
private DataProcessorUtils dataProcessorUtils;
private String employeeIndexName;
private static final String PERSON_ID_KEY = "personId";
private static final String PERSON_NAME_KEY = "personName";
#Inject
public EmployeePersistenceManager(#Named("employeeIndexName") String employeeIndexName,
EmployeeLambda employeeLambda,
MyTestDataPersistence myTestDataPersistence,
DataProcessorUtils dataProcessorUtils) {
this.employeeIndexName = employeeIndexName;
this.employeeLambda = employeeLambda;
this.myTestDataPersistence = myTestDataPersistence;
this.dataProcessorUtils = dataProcessorUtils;
createIndexIfNotExists(employeeIndexName);
}
public SearchDocumentResult searchPerson(EmployeeInput employeeInput) throws IOException {
return myTestDataPersistence
.searchDocument(employeeIndexName,
dataProcessorUtils.transformObjectDataPayloadToMap(employeeInput));
}
public EmployeeOutput invokeCreatePersonLambdaAndIndexData(final EmployeeInput employeeInput)
throws IOException {
String personRequestPayload = dataProcessorUtils.transformObjectDataInputJson(employeeInput);
Map<String, String> createdPersonOutput = this.employeeLambda.invokeLambda(personRequestPayload);
this.indexCreatedEmployee(employeeInput, createdPersonOutput);
return EmployeeOutput.builder().withPersonId(createdPersonOutput.get(PERSON_ID_KEY))
.withPersonName(createdPersonOutput.get(PERSON_NAME_KEY)).build();
}
public int indexCreatedEmployee(final EmployeeInput employeeInput,
final Map<String, String> createdPersonOutput) throws IOException {
employeeInput = modifyEmployeeInput(employeeInput);
String documentToIndex = dataProcessorUtils.transformObjectDataInputJson(employeeInput);
return myTestDataPersistence.indexDocument(this.employeeIndexName, documentToIndex);
}
public Map.Entry<String, Map<String, String>> invokeLambda(final String payload) {
return new AbstractMap.SimpleEntry<>(payload, this.employeeLambda.invokeLambda(payload));
}
private void createIndexIfNotExists(final String indexName) {
if (!myTestDataPersistence.doesIndexExist(indexName)) {
myTestDataPersistence.createIndex(CreateIndexInput.builder().indexName(indexName).build());
}
}
}
As you can see, the methods perform almost the same actions. Only the indexCreatedEmployee and indexCreatedJob methods from the classes have an extra step of processing the input.
Should I keep these classes as they are now without any relationships between them, or should I create an abstract persistence manager class and perform the following.
Move createIndexIfNotExists to the abstract class
Create abstract methods search(), invokeLambda() and indexCreatedData() methods and implement them in each child class. The data types MyJobInput and MyEmployeeInput are POJO classes that don't have any relationship. So I guess these methods I mentioned would then take "Object" parameters?
EmployeeLambda and JobLambda are again classes with no relationship between them. Another concern I had towards creating some sort of inheritance was that, Employee Lambda and JobLambda cannot be used inter-changeably. So was wondering if they should inherit the same parent class just because they're both lambda classes.
OR is there another way to go about this? Any advice would be much appreciated. Thank you very much in advance.
As promised yesterday, here is what I would do.
Create a Lambda interface and make JobLambda and EmployeeLambda implement it
public interface Lambda {
Map<String, String> invokeLambda(String payload);
}
public class JobLambda implements Lambda {
//... your implementation
}
public class EmployeeLambda implements Lambda {
//... your implementation
}
Do the same for DataPersistence
public interface DataPersistence {
boolean doesIndexExist(String indexName);
void createIndex(CreateIndexInput createIndexInput);
int indexDocument(String indexName, String documentToIndex);
SearchDocumentResult searchDocument(String indexName, Map<String, String> payloadMap);
}
public class MyDataPersistence implements DataPersistence {
//... your implementation
}
public class MyTestDataPersistence implements DataPersistence {
//... your implementation
}
Then create a parent class PersistenceManager which contains all the duplicated methods, parametrized for the type of input/output:
(Note: I didn't complete everything, but I did something just to make you understand the concept)
public class PersistenceManager<I, O> {
protected static final String ID = "Id";
protected static final String NAME = "Name";
private String indexName;
private Lambda lambda;
private DataPersistence dataPersistence;
private DataProcessorUtils dataProcessorUtils;
public PersistenceManager(String indexName, Lambda lambda, DataPersistence dataPersistence, DataProcessorUtils dataProcessorUtils) {
this.indexName = indexName;
this.lambda = lambda;
this.dataPersistence = dataPersistence;
this.dataProcessorUtils = dataProcessorUtils;
createIndexIfNotExists(indexName);
}
public SearchDocumentResult search(I input) {
return dataPersistence.searchDocument(indexName, dataProcessorUtils.transformObjectDataPayloadToMap(input));
}
public O invokeCreateLambdaAndIndexData(final I input) {
String requestPayload = dataProcessorUtils.transformObjectDataInputJson(input);
Map<String, String> createdOutput = this.lambda.invokeLambda(requestPayload);
//continue generalizing following the same logic
}
public int indexCreated(I input, Map<String, String> createdOutput) {
//continue generalizing following the same logic
}
private void createIndexIfNotExists(final String indexName) {
if (!dataPersistence.doesIndexExist(indexName)) {
dataPersistence.createIndex(CreateIndexInput.builder().indexName(indexName).build());
}
}
}
At this point, you can specialize your classes by simply choosing the parameters
... all the rest of the code will be shared in the parent class.
public class JobPersistenceManager extends PersistenceManager<MyJobInput, MyJobOutput> {
private static final String JOB_ID = "Job" + ID;
private static final String JOB_NAME = "Job" + NAME;
public JobPersistenceManager(String indexName, Lambda lambda, DataPersistence dataPersistence, DataProcessorUtils dataProcessorUtils) {
super(indexName, lambda, dataPersistence, dataProcessorUtils);
}
}
public class EmployeePersistenceManager extends PersistenceManager<MyEmployeeInput, MyEmployeeOutput> {
private static final String EMPLOYEE_ID = "Employee" + ID;
private static final String EMPLOYEE_NAME = "Employee" + NAME;
public EmployeePersistenceManager(String indexName, Lambda lambda, DataPersistence dataPersistence, DataProcessorUtils dataProcessorUtils) {
super(indexName, lambda, dataPersistence, dataProcessorUtils);
}
}
... and use them like this:
PersistenceManager employeePersistenceManager = new EmployeePersistenceManager(...);
employeePersistenceManager.search(employeeInput); //<-- the code is in the base class
I have a type which is extending HashMap<String, String>. As per the documentation here, it is possible to add a custom converter for the type. But it seems not working. The contents of the hashMap doesn't get converted, output looks like below;
"summary": {
"en": null
},
Any idea how to convert Label and its fields along with it's hashmap's contents?
Parent
#DynamoDbBean(converterProviders = {
CustomAttributeConverterProvider.class,
DefaultAttributeConverterProvider.class})
public class Summary extends BaseEntry {
private #Valid Label summary = null;
}
Child
#DynamoDbBean(converterProviders = {
CustomAttributeConverterProvider.class,
DefaultAttributeConverterProvider.class})
public class Label extends HashMap<String, String> {
private #Valid String en = null;
}
HashMapAttributeConverter
public class HashMapAttributeConverter implements AttributeConverter<Map<String, String>> {
private static AttributeConverter<Map<String, String>> mapConverter;
/** Default constructor. */
public HashMapAttributeConverter() {
mapConverter =
MapAttributeConverter.builder(EnhancedType.mapOf(String.class, String.class))
.mapConstructor(HashMap::new)
.keyConverter(StringStringConverter.create())
.valueConverter(StringAttributeConverter.create())
.build();
}
#Override
public AttributeValue transformFrom(Map<String, String> input) {
return mapConverter.transformFrom(input);
}
#Override
public Map<String, String> transformTo(AttributeValue input) {
return mapConverter.transformTo(input);
}
#Override
public EnhancedType<Map<String, String>> type() {
return mapConverter.type();
}
#Override
public AttributeValueType attributeValueType() {
return mapConverter.attributeValueType();
}
}
CustomAttributeConverterProvider
public class CustomAttributeConverterProvider implements AttributeConverterProvider {
private final List<AttributeConverter<?>> customConverters =
Arrays.asList(new HashMapAttributeConverter());
private final Map<EnhancedType<?>, AttributeConverter<?>> customConvertersMap;
private final AttributeConverterProvider defaultProvider =
DefaultAttributeConverterProvider.create();
public CustomAttributeConverterProvider() {
customConvertersMap =
customConverters.stream().collect(Collectors.toMap(AttributeConverter::type, c -> c));
}
#Override
public <T> AttributeConverter<T> converterFor(EnhancedType<T> enhancedType) {
return (AttributeConverter<T>)
customConvertersMap.computeIfAbsent(enhancedType, defaultProvider::converterFor);
}
}
#Override
public <T> AttributeConverter<T> converterFor(EnhancedType<T> type) {
// in this method you have to return only your converter based on type
// otherwise null should be returned. It will fix your issue.
}
I want to return a filled Map with my mocked Object, but the size of the Map is always Null. The mocked Object "CommandLineValues options" is not Null and also the Boolean variable "doCleanFirst" I can mock successfully.
Here is my Testclass:
#RunWith(MockitoJUnitRunner.class)
public class IndexBMECatTest {
#InjectMocks
private IndexBMECat classUnderTest;
#Mock
private CommandLineValues options;
#Test
public void testAccessoryItemHasNoDublicates() {
Map<String, String> testMap = new HashMap<>();
testMap.put("key", "value");
when(options.getCleanFirst()).thenReturn(false);
when(options.readWhitlist()).thenReturn(testMap);
classUnderTest.run();
}
}
Here is the constructor of my class where the code start, the tested Method is not relevant:
private boolean doCleanFirst;
private Map<String, String> whiteList;
public IndexBMECat(TransportClient client, CommandLineValues options, BMECatReader reader) throws Exception {
this.doCleanFirst = options.getCleanFirst();
this.whiteList = options.readWhitlist();
if (whiteList.isEmpty()) {
throw new Exception("Missing whiteList");
}
}
I also tried other variants:
Mock the Map and the return value of the method "isEmpty"
Initialize the Testclass and give the mocked Object to the constructor
But the whiteList has always the size = 0
Thx, this works now:
private IndexBMECat classUnderTest;
#Mock
private CommandLineValues options;
#Mock
private BMECatReader reader;
#Mock
TransportClient client;
#Before
public void setUp() throws Exception {
Map<String, String> testMap = new HashMap<>();
testMap.put("key", "value");
when(options.getCleanFirst()).thenReturn(false);
when(options.readWhitlist()).thenReturn(testMap);
classUnderTest = new IndexBMECat(client, options, reader);
}
#Test
public void testAccessoryItemHasNoDublicates() {
classUnderTest.run();
}
First I mock the methods which will be executed in the contructor and then I create the instance of my testclass.
I have a final class with private static method which is invoked inside another static method
public final class GenerateResponse{
private static Map<String, String> getErrorDetails(JSONObject jsonObject) {
// implementation
}
public static String method1(params...){
Map<String, String> map = getErrorDetails(new JsonObject());
// implementation
}
}
I need to mock the private static method call getErrorDetails(), but my test is calling the actual method. Here is my code:
#RunWith(PowerMockRunner.class)
#PrepareForTest(GenerateResponse.class)
public class GenerateResponseTest{
#Test
public void testFrameQtcErrorResponse() throws Exception {
Map<String, String> errorDtls = new HashMap<String, String>();
PowerMockito.spy(GenerateResponse.class);
PowerMockito.doReturn(errorDtls).when(GenerateResponse.class, "getErrorDetails", JSONObject.class);
String response = GenerateResponse.method1(params...);
}
You should use an argument matcher in the whenmethod. I've modified your code a little bit to run the test case.
Actual method
public final class GenerateResponse{
private static Map<String, String> getErrorDetails(JSONObject jsonObject) {
return null;
}
public static String method1() {
Map<String, String> map = getErrorDetails(new JSONObject());
return map.get("abc");
}
}
Test method
#RunWith(PowerMockRunner.class)
#PrepareForTest(GenerateResponse.class)
public class GenerateResponseTest {
#Test
public void testFrameQtcErrorResponse() throws Exception {
Map<String, String> errorDtls = new HashMap<String, String>();
errorDtls.put("abc", "alphabets");
PowerMockito.mockStatic(GenerateResponse.class, Mockito.CALLS_REAL_METHODS);
PowerMockito.doReturn(errorDtls).when(GenerateResponse.class,
"getErrorDetails", Matchers.any(JSONObject.class));
String response = GenerateResponse.method1();
System.out.println("response =" + response);
}
}
Output
response =alphabets
I am working on web application, which is deployed on apache tomcat web server. I want to associate data with current thread of http request. For this purpose I have created following class:
public class ThreadData {
private static final Map<Long, Map<String, String>> data = new HashMap<>();
public static Map<String, String> getDataMap(long threadId) {
if (data.get(threadId) == null) {
data.put(threadId, new HashMap<String, String>());
}
return data.get(threadId);
}
public static void put(String key, String value) {
long threadId = Thread.currentThread().getId();
getDataMap(threadId).put(key, value);
}
public static String get(String key) {
long threadId = Thread.currentThread().getId();
return getDataMap(threadId).get(key);
}
}
I want to know if such kind of solution is right and safe for this problem .
What you are trying to achieve is covered by ThreadLocal class, in your case it would be
ThreadLocal<Map<String, String>> data = new ThreadLocal<Map<String, String>>() {
#Override
protected Map<String, String> initialValue() {
return new HashMap<>();
}
};
If you still want to use put or get, you may define them in such a way:
public static void put(String key, String value) {
data.get().put(key, value);
}
public static String get(String key) {
return data.get().get(key);
}