I have a folder path set in system variable through JVM arguments in Eclipse and I am trying to access it in my class as:
System.getProperty("my_files_path").
While writing junit test method for this class, I tried mocking this call as test classes do not consider JVM arguments. I have used PowerMockito to mock static System class and tried returning some path when System.getProperpty is being called.
Had #RunWith(PowerMockRunner.class) and #PrepareForTest(System.class) annotations at class level. However, System class is not getting mocked as a result I always get null result.
Any help is appreciated.
Thanks Satish. This works except with a small modification. I wrote PrepareForTest(PathFinder.class), preparing the class I am testing for test cases instead of System.class
Also, as mock works only once, I called my method right after mocking.
My code just for reference:
#RunWith(PowerMockRunner.class)
#PrepareForTest(PathInformation.class)
public class PathInformationTest {
private PathFinder pathFinder = new PathFinder();
#Test
public void testValidHTMLFilePath() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("my_files_path")).thenReturn("abc");
assertEquals("abc",pathFinder.getHtmlFolderPath());
}
}
There are certain classes PowerMock can't mock in the usual way. See here:
https://code.google.com/p/powermock/wiki/MockSystem
This, however, may still not work. In order of "good design" preference, you can fall back to these:
Refactor your code! Using a System property for passing a file path around is probably not the best way. Why not use a properties file loaded into a Properties object? Why not use getters/setters for the components that need to know this path? There are many better ways to do this.
The only reason I could think of not to do this is you're trying to wrap a test harness around code you "can't" modify.
Use #Before and #After methods to set the System property to some known value for the test(s). You could even make it part of the #Test method itself. This will be FAR easier than attempting to mock through PowerMock. Just call System.setProperty("my_files_path","fake_path");
System class is declared as final and cannot be mocked by libraries such as PowerMock. Several answers posted here are incorrect. If you are using Apache System Utils you can use getEnvironmentVariable method instead of calling System.getenv directly. SystemUtils can be mocked since it is not declared as final.
Set the system property in your test and ensure that it is restored after the test by using the rule RestoreSystemProperties of the library System Rules.
public class PathInformationTest {
private PathFinder pathFinder = new PathFinder();
#Rule
public TestRule restoreSystemProperties = new RestoreSystemProperties();
#Test
public void testValidHTMLFilePath() {
System.setProperty("my_files_path", "abc");
assertEquals("abc",pathFinder.getHtmlFolderPath());
}
}
The System.setter or getter method should be put in a user defined method and that method can be mocked to return the desired property in unit test.
public String getSysEnv(){
return System.getEnv("thisprp");
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(System.class)
public class MySuperClassTest {
#Test
public void test(){
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("java.home")).thenReturn("abc");
System.out.println(System.getProperty("java.home"));
}
}
Sailaja add System.class because as per the power mock guidelines for static,private mocking you should add the class in prepare for test.
#PrepareForTest({PathInformation.class,System.class})
Hope this helps.let me know if it doesn't work
Related
my problem is that my unit test are slow because I'm publishing in a topic in those unit test, I would like to mock or change its behavior in some way. I was thinking in use reflection for this class and change the method behavior but I'm not sure if that is possible.
This is the behavior that I like to mock or change:
TopicCall.builder()
.toTopic(XXXX)
.withAttribute(XXXXXX, XXXXX)
.withAttribute(XXXXX, XXXXXX)
.withAttribute(XXXXX,XXXXX)
.publish();
I would like to do this because publis() is a real invocation and the test is slow and causing some problems in jenkins, because several unit test are publishing at the same time.
The Topic class is a public class with a static builder method which return a class instance, just like the next one:
public static TopicCall builder() {
return new TopicCall();
}
My problem is that I just acceding the method of this class from outside and I'm not sending the class in the constructor as example and I'm not able to mock its behavior, I'm not able to modify the TopicCall class because it is a .class utility from a jar, besides that I'm not able to use PowerMockito or another library, just Mockito, is there any way to achieve that?
Thanks!
Disclaimer: I missed the fact that PowerMock is forbidden for the author, but the answer could be useful for other users with the same problem.
PowerMock
As far as you want to mock a static method, then Mockito is not the solution.
This could be done using PowerMock.
PowerMock uses ClassLoader way for mocking, which could significantly increase tests time to run.
Here is an examle on Baeldung how to mock static methods.
Solution scratch:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ TopicCall.class })
public class Test {
#Test
void test() {
mockStatic(TopicCall.class);
when(TopicCall.builder()).thenReturn(/*value to be returned*/ null);
// the test code...
}
}
I have a code somewhat like this below:
Class A {
public boolean myMethod(someargs) {
MyQueryClass query = new MyQueryClass();
Long id = query.getNextId();
// some more code
}
}
Class MyQueryClass {
....
public Long getNextId() {
//lot of DB code, execute some DB query
return id;
}
}
Now I'am writing a test for A.myMethod(someargs). I want to skip the real method query.getNextId() and instead return a stub value. Basically, I want to mock MyQueryClass.
So in my test case, I have used:
MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);
boolean b = A.getInstance().myMethod(args);
//asserts
I used #RunWith(PowerMockRunner.class) and #PrepareForTest({MyQueryClass.class}) in the beginning of my test class.
But when I debug the test, it is still calling the real method getNextId() of the MyQueryClass class.
What am I missing here? Can anyone help as I am new to Mockito and PowerMockito.
You need to put the class where the constructor is called into the #PrepareForTest annotation instead of the class which is being constructed - see Mock construction of new objects.
In your case:
✗ #PrepareForTest(MyQueryClass.class)
✓ #PrepareForTest(A.class)
More general:
✗ #PrepareForTest(NewInstanceClass.class)
✓ #PrepareForTest(ClassThatCreatesTheNewInstance.class)
As #TrueDub mentioned in his accepted reply, you need to add the class where the constructor is called to the #PrepareForTest.
However, if you do this, coverage for that class as reported by eclemma and Sonar will be zero for that class
Powermockito wiki
We are going to replace Javassist with ByteBuddy (#727) and it should
help to resolve this old issue. But right now there is NO WAY TO USE
PowerMock with JaCoCo On-the-fly instrumentation. And no workaround to
get code coverage in IDE.
So the solution here would be to refactor the actual code to use a static factory that would return an instance of that class and then statically mock it.
Perhaps you can simply use
Mockito.doReturn(value).when(xxx)
I have the following instruction in Java:
String path = MyClass.class.getClassLoader().getResource(fileName).getPath();
I need to mock the ClassLoader returned by MyClass.class.getClassLoader(), using Mockito and Powermock.
I tried with this:
#Mock ClassLoader classLoader;
whenNew(ClassLoader.class).withAnyArguments().thenReturn(classLoader);
But it doesn't work.
Does anybody know how to do it?
As the comments indicate: you are approaching this on the wrong level.
Looking at your code:
String path = MyClass.class.getClassLoader().getResource(fileName).getPath();
You see, the MyClass.class.getClassLoader().getResource(fileName) part; that is "built-in" technology.
What I mean is: unless other parts of your code mess around with the ClassLoader, then the above does exactly what it is supposed to do. There is absolutely no need to test that extensively. You only care about: here class, and file name; something give me a Path. That is what matters to you. Thus: abstract that!
In other words: you just go forward and add that additional abstraction, like:
public interface PathProvider {
public Path getPathFromUrl(Class<?> clazz);
}
A simple implementation could look like
public class PathProviderImpl implements PathProvider {
#Override
Path getPathFromUrl(Class<?> clazz, String fileName) {
return clazz.getClassLoader().getResource(fileName).getPath();
}
or something alike. Please note: you can write a simple unit test that checks this implementation, too.
But the core point is: instead of making the static call within your production code, you use a (mocked) instance of that interface.
No need for PowerMock, no need for static mocking; just nice, plain mockito stuff!
Besides: the above fixes your design problem. You created hard to test production code; and you don't fix that by using the big PowerMock hammer; you fix it improving the bad design.
You are mocking a new Statement, but you have not any new statement in your Code
As for my understanding, you should:
Mock static MyClass
Mock getClassLoader()
create a mock for ClassLoader
mock method getResource
Something as follows:
#Mock ClassLoader classLoader;
PowerMockito.mockStatic(MyClass.class);
BDDMockito.given(MyClass.getClassLoader()).willReturn(classLoader);
PowerMockito.doReturn("desiredResource").when(classLoader).getResource(Mockito.anyString());
Also you may need to set at the beginning of your test class the following lines:
#RunWith(PowerMockRunner.class)
#PowerMockListener(AnnotationEnabler.class)
#PrepareForTest({MyClass.class})
public class yourTestClass....
Are there any best practices to get Junit execute a function once in a test file , and it should also not be static.
like #BeforeClass on non static function?
Here is an ugly solution :
#Before void init(){
if (init.get() == false){
init.set(true);
// do once block
}
}
well this is something i dont want to do , and i am looking for an integrated junit solution.
A simple if statement seems to work pretty well too:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:test-context.xml"})
public class myTest {
public static boolean dbInit = false;
#Autowired
DbUtils dbUtils;
#Before
public void setUp(){
if(!dbInit){
dbUtils.dropTables();
dbUtils.createTables();
dbInit = true;
}
}
...
To use an empty constructor is the easiest solution. You can still override the constructor in the extended class.
But it's not optimal with all the inheritance. That's why JUnit 4 uses annotations instead.
Another option is to create a helper method in a factory/util class and let that method do the work.
If you're using Spring, you should consider using the #TestExecutionListeners annotation.
Something like this test:
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners({CustomTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class})
#ContextConfiguration("test-config.xml")
public class DemoTest {
Spring's AbstractTestExecutionListener contains for example this empty method that you can override:
public void beforeTestClass(TestContext testContext) throws Exception {
/* no-op */
}
NOTE: DO NOT overlook/miss DependencyInjectionTestExecutionListener while adding custom TestExecutionListeners. If you do, all the autowires will be null.
If you don't want to set up static initializers for one time initialization and are not particular about using JUnit, take a look at TestNG. TestNG supports non-static, one-time initialization with a variety of configuration options, all using annotations.
In TestNG, this would be equivalent to:
#org.testng.annotations.BeforeClass
public void setUpOnce() {
// One time initialization.
}
For teardown,
#org.testng.annotations.AfterClass
public void tearDownOnce() {
// One time tear down.
}
For the TestNG equivalent of JUnit 4's #Before and #After, you can use #BeforeMethod and #AfterMethod respectively.
Easily use #BeforeAllMethods/#AfterAllMethods annotations to run a method inside the instance context (non-static), where all injected values will be available.
There is a special testing library for this:
https://mvnrepository.com/artifact/org.bitbucket.radistao.test/before-after-spring-test-runner/0.1.0
https://bitbucket.org/radistao/before-after-spring-test-runner/
The only limitation: works only for Spring testing.
(I'm the developer of this testing library)
I've never tried but maybe you can create a no-argument constructor and call you function from there?
The article discuss 2 very nice solutions for this problem:
"clean" junit with custom Runner (using interface but you could extend it with a custom annotation e.g. #BeforeInstance)
Spring execution listeners as mentioned by Espen before.
UPDATE: Please see the comment by Cherry for why the suggestion below is flawed. (Am keeping the answer on here rather than deleting as the comment may provide useful information to others as to why this doesn't work.)
Another option worth considering if using dependency injection (e.g. Spring) is #PostConstruct. This will guarantee dependency injection is complete, which wouldn't be the case in a constructor:
#PostConstruct
public void init() {
// One-time initialization...
}
Just use #BeforeClass:
#BeforeClass
public static void init() {
}
It doesn't make sense for init to be non-static because each test is run in a separate instance. The instance
that init is run on would not match the instance of any test.
The only reason that you might want it to be non-static is to override it in subclasses, but you can do this
with static methods too. Just use the same name, and only the subclass init method will be called.
I have a code somewhat like this below:
Class A {
public boolean myMethod(someargs) {
MyQueryClass query = new MyQueryClass();
Long id = query.getNextId();
// some more code
}
}
Class MyQueryClass {
....
public Long getNextId() {
//lot of DB code, execute some DB query
return id;
}
}
Now I'am writing a test for A.myMethod(someargs). I want to skip the real method query.getNextId() and instead return a stub value. Basically, I want to mock MyQueryClass.
So in my test case, I have used:
MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);
boolean b = A.getInstance().myMethod(args);
//asserts
I used #RunWith(PowerMockRunner.class) and #PrepareForTest({MyQueryClass.class}) in the beginning of my test class.
But when I debug the test, it is still calling the real method getNextId() of the MyQueryClass class.
What am I missing here? Can anyone help as I am new to Mockito and PowerMockito.
You need to put the class where the constructor is called into the #PrepareForTest annotation instead of the class which is being constructed - see Mock construction of new objects.
In your case:
✗ #PrepareForTest(MyQueryClass.class)
✓ #PrepareForTest(A.class)
More general:
✗ #PrepareForTest(NewInstanceClass.class)
✓ #PrepareForTest(ClassThatCreatesTheNewInstance.class)
As #TrueDub mentioned in his accepted reply, you need to add the class where the constructor is called to the #PrepareForTest.
However, if you do this, coverage for that class as reported by eclemma and Sonar will be zero for that class
Powermockito wiki
We are going to replace Javassist with ByteBuddy (#727) and it should
help to resolve this old issue. But right now there is NO WAY TO USE
PowerMock with JaCoCo On-the-fly instrumentation. And no workaround to
get code coverage in IDE.
So the solution here would be to refactor the actual code to use a static factory that would return an instance of that class and then statically mock it.
Perhaps you can simply use
Mockito.doReturn(value).when(xxx)