Mock FileInputStream in FileReader can't work using PowerMock - filereader

I noticed that in FileReader constructor, the FileInputStream is created. So I what to Mock it in the FileReader class, but it can't work. Can anyone figure it out?
The code it like below:
package util;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.junit.Assert;
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({ FileReader.class, ContentReader.class})
public class FileReaderTest {
#Test
public void testGetContent() throws Exception {
File file = PowerMockito.mock(File.class);
InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream("123".getBytes()));
PowerMockito.whenNew(InputStreamReader.class)
.withArguments(Mockito.any(FileInputStream.class)).thenReturn(isr);
Assert.assertEquals("123", ContentReader.getContent(file));
}
}
class ContentReader {
public static String getContent(File file) throws IOException {
String content = "unknown";
BufferedReader in = null;
in = new BufferedReader(new FileReader(file));
content = in.readLine();
in.close();
return content;
}
}

Shot answer - it's impossible, because to mock system classes the PowerMock should be able to modified a client class which uses system class. In your case both classes: who uses and what is used are system classes. More you can read here (it's about static calls of system classes, but same true for mocking constructor call)
Also, please check this good point: don't mock what you don't own. For you it means:
You should wrap reading data from file via util class which you can mock
Write an integration test for your util class. If ContentReader
is an util class then you shouldn't write unit test for it.

Related

Prtining method arguments using byte buddy API

I am working on a project where I need access method arguments during execution.
Is it possible to print method arguments using byte buddy framework? any sample code on this using javaagent is highly appreciated.
Yes, this is possible. You can use MethodDelegation or Advice to inject your code and then use the #AllArguments annotation to get hold of the actual arguments.
The question is, how do you create your code in your project? You can either use a Java agent with the AgentBuilder or create proxy subclasses using ByteBuddy instances. Refer to the documentation and the mentioned classes javadoc to find out how this is done.
Here is an example of how this can be implemented using MethodDelegation. I use it to measure the execution time of methods. I specifically did not begin to remove the extra code, because I want to more fully reveal the capabilities of Byte Buddy.
package md.leonis.shingler;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.matcher.ElementMatchers;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
public class MeasureMethodTest {
public static void main(String[] args) throws InterruptedException {
premain(ByteBuddyAgent.install());
for (int i = 0; i < 4; i++) {
SampleClass.foo("arg" + i);
}
}
public static void premain(Instrumentation instrumentation) {
new AgentBuilder.Default()
.type(ElementMatchers.nameStartsWith("md.leonis.shingler"))
.transform((builder, type, classLoader, module) ->
builder.method(ElementMatchers.any()).intercept(MethodDelegation.to(AccessInterceptor.class))
).installOn(instrumentation);
}
public static class AccessInterceptor {
#RuntimeType
public static Object intercept(#Origin Method method, #SuperCall Callable<?> callable, #AllArguments Object[] args) throws Exception {
long start = System.nanoTime();
try {
return callable.call();
} finally {
if (method.getAnnotationsByType(Measured.class).length > 0) {
String params = Arrays.stream(args).map(Object::toString).collect(Collectors.joining(", "));
System.out.println(method.getReturnType().getSimpleName() + " " + method.getName() + "("+ params +") took " + ((System.nanoTime() - start) / 1000000) + " ms");
}
}
}
}
public static class SampleClass {
#Measured
static void foo(String s) throws InterruptedException {
Thread.sleep(50);
}
}
}
This example measures the execution time of all methods found in the md.leonis.shingler package and marked with the #Measured annotation.
To run it, you need two libraries: byte-buddy and byte-buddy-agent.
The result of work:
void foo(arg0) took 95 ms
void foo(arg1) took 50 ms
void foo(arg2) took 50 ms
void foo(arg3) took 50 ms
Note that the console displays the values of all arguments passed to the method. This is the answer to the question asked.
Here is the annotation example:
package md.leonis.shingler;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Measured {
}
To be honest, I was not able to directly configure filtering by annotations in the Agent. Here is an example (not working):
new AgentBuilder.Default()
.type(ElementMatchers.isAnnotatedWith(Measured.class))
.transform((builder, type, classLoader, module) ->
builder.method(ElementMatchers.any()).intercept(MethodDelegation.to(AccessInterceptor.class))
).installOn(instrumentation);
If someone knows how to do this, please comment below.

In alfresco repository how to create link for one folder to another folder using java api

Hi guys i am beginner in alfresco.I have done many services such as creating folder,subfolder,uploading document,downloading document,creating permissions using cmis.
But i am not able to create link of one folder to another folder using cmis.
Somebody told me its not possible using cmis.
Somehow i got this link http://basanagowdapatil.blogspot.in/2011/01/code-for-creating-links-in-alfresco.html.
But this code is not in cmis.
I have never done this kind of programming.
Can somebody suggest me how to do this program in maven.
What dependency or jars i should add.
It is better if someone explain me step by step(in sense how to give authentication).
Thanks in advance
I got my answer and we can do the same using CMIS API.
import java.util.HashMap;
import java.util.Map;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import com.bizruntime.alfresco.session.CreateSession;
import com.bizruntime.alfresco.util.Config;
public class CreateLink {
static Logger log = Logger.getLogger(CreateLink.class);
public static void getLink() {
// creating Session
Session cmiSession = new CreateSession().getSession();
log.debug("Session Created...");
Map<String,Object> properties = new HashMap<>();
properties.put(PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_ITEM.value());
// Define a name and description for the link
properties.put(PropertyIds.NAME, Config.getConfig().getProperty("nameOfLink"));
properties.put("cmis:description", Config.getConfig().getProperty("linkDescription"));
properties.put(PropertyIds.OBJECT_TYPE_ID, "I:app:filelink");
// Define the destination node reference
properties.put("cm:destination", Config.getConfig().getProperty("destination-nodRef"));
// Choose the folder where the link to be create
Folder rootFoler = cmiSession.getRootFolder();
Folder targerFolder = (Folder) cmiSession.getObjectByPath(rootFoler.getPath() + Config.getConfig().getProperty("targetFolder"));
cmiSession.createItem(properties, targerFolder);
log.info("Link Created Successfully....");
}
public static void main(String[] args) {
BasicConfigurator.configure();
CreateLink cl = new CreateLink();
cl.getLink();
}
}
Code for creating folder link:
import java.util.HashMap;
import java.util.Map;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import com.bizruntime.alfresco.session.CreateSession;
import com.bizruntime.alfresco.util.Config;
public class CreateLink {
static Logger log = Logger.getLogger(CreateLink.class);
public static void getLink() {
// creating Session
Session cmiSession = new CreateSession().getSession();
log.debug("Session Created...");
Map<String,Object> properties = new HashMap<>();
properties.put(PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_ITEM.value());
// Define a name and description for the link
properties.put(PropertyIds.NAME, Config.getConfig().getProperty("nameOfLink"));
properties.put("cmis:description", Config.getConfig().getProperty("linkDescription"));
properties.put(PropertyIds.OBJECT_TYPE_ID, "I:app:filelink");
// Define the destination node reference
properties.put("cm:destination", Config.getConfig().getProperty("destination-nodRef"));
// Choose the folder where the link to be create
Folder rootFoler = cmiSession.getRootFolder();
Folder targerFolder = (Folder) cmiSession.getObjectByPath(rootFoler.getPath() + Config.getConfig().getProperty("targetFolder"));
cmiSession.createItem(properties, targerFolder);
log.info("Link Created Successfully....");
}
public static void main(String[] args) {
BasicConfigurator.configure();
CreateLink cl = new CreateLink();
cl.getLink();
}
}

How to import a custom component with resource into SceneBuilder?

I have created a bunch of custom nodes for my project, by subclassing existing ones.
For example:
package sample;
import javafx.scene.control.Button;
public class MyCustomButton extends Button {
public MyCustomButton() {
System.out.println("This is my custom button...");
}
}
This is working fine, I create a jar file and I can import it into Scenebuilder.
However if my custom node uses a resource, and I try to import the jar in Scenebuilder, the custom component won't show up in the Import Dialog.
package sample;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
public class MyCustomButton extends Button {
public MyCustomButton() {
Image image = new Image("sample/picture.gif");
System.out.println("This is my custom button...");
}
}
How can I convince Scenebuilder to import my custom components if they contain resources? The jar file has all the needed resources, and a component working fine in code, but I would like to be able to use it in Scenebuilder as well.
I did for you:)
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class MyCustomButton extends Button {
public MyCustomButton() {
final ImageView imageView = new ImageView();
Image image = new Image(getClass().getClassLoader().getResource("sample/picture.png").toExternalForm());
imageView.setImage(image);
this.setGraphic(imageView);
System.out.println("This is my custom button...");
}
}
Check the analysis report on SB. Click on the settings icon on the right hand side of Library, then select "Custom Library Folder" --> "Show Jar Analysis Report". You can see some useful hints. Maybe this helps you.

Processing an InputStream to OutputStream on the fly through a HttpServlet

I'm trying to process a large text file through a HttpServlet (tomcat).
As this file can be large and the process should be very fast, I don't want to upload the file on the server and I've used the method HttpRequest.getInputStream to process the input on the fly. For example, I want to transform the input to upper-case with the code below:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#SuppressWarnings("serial")
public class EchoServlet extends HttpServlet
{
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
OutputStream out=null;
InputStream in=req.getInputStream();
if(in==null) throw new IOException("input is null");
try
{
resp.setContentType("text/plain");
out=resp.getOutputStream();
int c;
while((c=in.read())!=-1)
{
out.write((char)Character.toUpperCase(c));
}
}
catch(IOException err)
{
//ignore
}
finally
{
if(out!=null) out.flush();
if(out!=null) out.close();
in.close();
}
}
}
I invoked my servlet with CURL:
curl -s -d #big.file.txt "http://localhost:8080/test/toupper"
1) processing the input on the fly through a servlet, is it a good/common practice ?
2) my code seems to remove the carriage return ('\n') . Why ?
Thanks
1) processing the input on the fly through a servlet, is it a good/common practice ?
Depends on the functional requirement. I would personally have used a servlet which accepts HTTP multipart/form-data requests instead of raw request bodies. This way it's reuseable on normal HTML forms.
2) my code seems to remove the carriage return ('\n') . Why ?
The given code example doesn't do that. Maybe you've oversimplified it and you was originally using BufferedReader#readLine() while not using PrintWriter#println(). The readLine() indeed eats CRLFs.
There are more issues/inefficiencies in the given code snippet as well, but I can't give a decent answer on that as you seem not to actually be running the code as you posted in the question.

How to use fonts in external SWF files

What I would like to do is a flex app, that uses fonts that are available in external swf.
What I have succeded so far is:
to create a AS class hat holds the embedded font:
package
{
import flash.display.Sprite;
public class _Arial extends Sprite
{
[Embed(source='C:/WINDOWS/Fonts/ARIAL.TTF', fontName='_Arial', unicodeRange='U+0020-U+002F,U+0030-U+0039,U+003A-U+0040,U+0041-U+005A,U+005B-U+0060,U+0061-U+007A,U+007B-U+007E')]
public static var _MyArial:Class;
}
}
compiled this into a swf with following command: mxmlc.exe -static-link-runtime-shared-libraries=true _Arial.as
When I try to load the font from my flex app, this fails with following error message:
ArgumentError: Error #1508: The value specified for argument font is invalid.
at flash.text::Font$/registerFont()
at valueObjects::FontLoader/fontLoaded()[C:\Documents and Settings\nutrina\Adobe Flash Builder 4\flex_pdf\src\valueObjects\FontLoader.as:33]
This is the code where I try to load the SWF file:
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLRequest;
import flash.text.*;
import mx.collections.ArrayCollection;
import mx.core.FontAsset;
public class FontLoader extends Sprite {
public function FontLoader(url:String) {
super();
loadFont(url);
}
private function loadFont(url:String):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, fontLoaded);
loader.load(new URLRequest(url));
}
private function fontLoaded(event:Event):void {
var fontList:ArrayCollection = new ArrayCollection(Font.enumerateFonts(true));
var FontLibrary:Class = event.target.applicationDomain.getDefinition("_Arial") as Class;
trace("FontList: " + fontList)
trace("FontLibrary: " + FontLibrary)
trace("FontLibrary._Arial: " + FontLibrary._MyArial)
Font.registerFont(FontLibrary._MyArial);
fontList = new ArrayCollection(Font.enumerateFonts(true));
trace("Font list: " + fontList)
}
}
}
The font file is definitely not corrupt because if I put the _Arial class from the code above into the Flex application, the embedding works. So my guess is that probably I missed some compilation options?
I am using Adobe Flash Builder 4.
I would appreciate any help on this matter.
Thanks,
Gerald
Could be a problem with class name conflicts. I wrestled with an external font loading issue for hours. Turns out my font class was called "Main", and so was the application that was trying to load it. The font never got registered correctly.

Resources