I am trying to test utility method which check if particular class is on class path, if yes return true else return false.
Why I am doing this: I have to independent classes extending same class, and only one of it will be on classpath. Need to do specific thing if one particular is on classpath.
Using kind of below method to check if particular class is on class path.
This check will be done only once after first request.
I'd checked Class.forName() also but decided to go with below approach.
My utility method looks something like this:
public static boolean isMyClassOnClassPath() {
try {
ClassLoader.getSystemClassLoader().loadClass("com.MyClass");
return true;
} catch (ClassNotFoundException ex) {
return false;
}
}
Checking false condition is easy as particular class is not not the ClassPath.
I'm trying to write Junit for positive scenario when this method will return true.
#Test
public void isMyClassOnClassPathShouldReturnTrueWhenMyClassIsOnClassPath() throws Exception{
PowerMockito.mockStatic(MyClass.class);
ClassLoader classLoader = PowerMockito.mock(ClassLoader.class);
PowerMockito.mockStatic(ClassLoader.class);
PowerMockito.when(ClassLoader.getSystemClassLoader()).thenReturn(classLoader);
//trying to mock classLoader.loadClass, below way is incorrect
//PowerMockito.when(classLoader.loadClass("com.MyClass")).thenReturn(Class<java.lang.Object.class>);
Assert.assertTrue(MyClassUtil.isMyClassOnClassPath());
}
So is it possible to mock classLoader.loadClass() method?
Honestly: don't even think about doing something like that.
In short, you are like a person sitting on a tree that starts cutting random limbs of the tree that person is sitting on. Meaning: this is a central part of the JVM. Assume your mocking would work: then every caller to that method would receive your mocked loader! So, when your test case itself wanted to load some classes, it would run into your mock!
And as almost usual, when people claim "I need to user Powermock for xyz" your real problem is a different one: you created untestable code. By making that static call there, you prevent yourself from testing your code!
For starters, you can have a look here to learn how to write testable code. But in case you are curious how you could fix your design:
class ClassPathChecker {
private final ClassLoader classLoader;
ClassPathChecker() { this(ClassLoader.getSystemClassLoader()); }
ClassPathChecker(ClassLoader classLoader) {
this.classLoader = this.classLoader);
}
boolean canClassBeLoaded(String className) {
try {
classLoader.loadClass ...
The above uses dependency injection to insert a mocked ClassLoader; which gives you full control over everything that is going on. Without using Powermock at all.
And out of curiosity: why do you restrict yourself to the System classloader? Wouldn't a simple call like Class.forName("yourclass") tell you the same?
Related
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....
I am working on spring based project and writing unit test case using JUnit + Mockito. I am facing a problem while stubbing boolean value to a private method of same test class (after changing access level to public, still I have failed to stub the boolean value).
Below code snippet shows the simulation of same problem
class ABC {
public String method1(User userObj){
String result = "";
if(!isValidUser(userObj.getSessionID())){
return "InvalidUser";
} else {
// execute some logic
}
return result;
}
private boolean isValidUser(String sessionId) {
// Here it calls some other class to validate the user
if (sessionId == null || UserSessionPool.getInstance().getSessionUser(sessionId) == null) {
return false;
} else {
return true;
}
}
}
Here, I would like to write a test case for method1(). In class ABC I have a method called isValidUser() which helps to identify the user with in a session by looking into a global session pool which holds all logged-in used details i.e. UserSessionPool.getInstance().getSessionUser(sessionId).
While testing method1(), the moment test controller triggers isValidUser(userObj.getSessionID()) I would like to return true from isValidUser() method, so that I can continue to test rest of the implementation logic.
So far I have tried following ways using spy and mocked object to call the isValidUser() method and try to return true but nothing worked well.
Using PowerMockito
PowerMockito.doNothing().when(spyed_ABC_ClassObject, "isValidUser", true);
or
PowerMockito.doReturn(true).when(cntrl, "isValidUser", Mockito.anyString());
Using Whitebox
Whitebox.invokeMethod(spyed_ABC_ClassObject, "isValidUser", Mockito.anyString());
Using Mockito.when
when(spyed_ABC_ClassObject.isValidUser(Mockito.anyString())).thenReturn(true);
or
Mockito.doNothing().when(spyed_ABC_ClassObject).isValidUser(Mockito.anyString());
The other answer is: fix your design instead of turning to the big PowerMock hammer.
Yes, PowerMock allows you to mock static methods. But you should understand: static is an abnormality in good OO design. You only use it when you have very good reasons. As it leads to tight coupling between your classes, and surprise: it breaks your ability to write reasonable unit tests. Yes, PowerMock works; but sometimes, it does not. When your classes grow, and you do more and more things "statically", because, you know, PowerMock will do the job ... be prepared for bizarre fails at some point, that can take hours to hunt down; without ever finding real bugs in your production code.
So, consider an alternative:
Do not use static method calls. And if there is some static method around that you can't touch; consider building a small interface around that.
Instead: use dependency injection and simply pass objects implementing some interface into your production code. Because you can mock such objects without the need for PowerMock(ito).
In that sense: you simply created hard to test code. Now you intend to fix that using PowerMock. The other way (much more reasonable in my eyes) is to learn how to write testable code in the first place. Here is a good starting point for that.
Can you please try this out.
#Before
public void setUp() {
UserSessionPool mockConnectionPool = Mockito.mock(UserSessionPool.class);
}
#Test
public void testName() throws Exception {
//given
PowerMockito.mockStatic(UserSessionPool.class);
BDDMockito.given(UserSessionPool.getInstance()(...)).willReturn(mockConnectionPool);
Mockito.when(mockConnectionPool.getSessionUser(Mockito.anylong())).thenReturn(something);
//then
PowerMockito.verifyStatic();
}
Hope this helps. Happy coding !
I'm developing a Play Framework 2 application in Java, and I'm wondering if I can use static helper classes.
For example, I want to know if a user is logged and have completed its profile. This test take a few lines, may be subject to change, and is used a lot in the application.
So I write a class with these tests in one method with one argument (the Session object) that I use everywhere.
But I have to instantiate a class each time to use the method, so at scale it may be inefficient. Is it safe to make it static ? If it is, what other play object can I use safely as a parameter ?
When you say "test", I assume you mean some checking logic instead of unit tests.
In that case, you can use dependency injection instead of static helpers.
https://www.playframework.com/documentation/2.3.x/JavaInjection
The above link shows an example of how to use Guice to inject your controller when processing requests.
So previously your controller would be:
public class Application extends Controller {
public static Result index() {
if (YourStaticHelper.yourStaticMethod.isOk()) {
return ok("It works!");
}
else {
return forbidden("NO");
}
}
}
Now it would become:
public class Application extends Controller {
#Inject
YourStaticHelperInterface checker;
public Result index() { // no longer static
if (checker.isOk()) {
return ok("It works!");
}
else {
return forbidden("NO");
}
}
}
The difference is in the previous one if you somehow need a new helper, you would have to change the controller code to adapt it to the change, whereas in the second you just need to inject a different implementation at runtime as isOk() there becomes a contract in the interface.
The benefit? Who knows. If I'm writing something completely myself at home or the controller code is actually tightly coupled with the helper, I would choose the first. If I'm working with others in a company, I would pick the second. It's all about software engineering shit but that's how things work.
I've implemented a feature in my jUnit tests that takes, for every test case, a fresh copy of a data source. This copy is taken in a folder specific for each test case. The idea is that every test case can start from a clean situation, manipulate it and let it as such after the run. This is often useful when the test fails for analysing the problem.
For now I have to call this feature directly in the test method because I don't know how to retrieve the current test name:
public void testTest1() {
TestHelper th=TestHelper.create("testTest1",subPathToDataSource);
// do the test...
Path dataPath = th.getDataPath();
...
}
I would like to be able to write something like this:
Path dataPath;
#Before
public initTest() {
th=TestHelper.create(SomeJUnitObject.getCurrentTestName(),subPathToDataSource);
...
}
public void testTest1() {
// do the test...
Path dataPath = th.getDataPath();
...
}
Until now I found as answers : "You don't need to know that"... But I do need it !
Is this possible ?
Kind regards
Look at the TestName rule.
You should be able to add in your test class:
#Rule TestName name=new TestName();
And then access it.
(On phone, so can't check versions support/details - might be 4.x only)
Here is an alternative approach; create an abstract class which your "real" test classes inherit.
I have several such examples in my projects and here I will give one, mainly testing for individual JSON Patch operations.
All my test files are JSON, and located under an appropriately named resource directory. The base, abstract class is JsonPatchOperationTest. And here is the full code of AddOperationTest which tests for JSON Patch's add operation:
public final class AddOperationTest
extends JsonPatchOperationTest
{
public AddOperationTest()
throws IOException
{
super("add");
}
}
And that's it! Not even one test method in this class, but of course your implementation may vary.
In your case you probably want to pass the directory name as a constructor argument, or the like.
I have a series of data each one containing info_A and info_B. I would like to:
if(info_A) {
run Test A
} else if(!info_A) {
run Test B
}
It is very important that only the Test actually run is shown in the JUnit GUI tree. How can I do this?
The following solutions do not work:
If I use the Assume.assumeTrue(conditon), I can Ignore a test but then it is still displayed as passed in the test.
Doing this:
Result result = JUnitCore.runClasses(TestStep1.class);
leads to the correct result but the JUnit tree is not built.
Using #Catagories also shows the failed tests, which is also what I don't want.
You can use Assume to turn tests on/off conditionally:
A set of methods useful for stating assumptions about the conditions in which a test is meaningful. A failed assumption does not mean the code is broken, but that the test provides no useful information.
You can do this with JUnit Rules.
There's a whole blog post dedicated to exactly your question here, but in short, you do the following:
Create a class that implements the org.junit.rules.TestRule interface. This interface contains the following method:
Statement apply(Statement base, Description description);
The base argument is actually your test, which you run by calling base.execute() -- well, the apply() method actually returns a Statement anonymous instance that will do that. In your anonymous Statement instance, you'll add the logic to determine whether or not the test should be run. See below for an example of a TestRule implementation that doesn't do anything except execute your test -- and yes, it's not particularly straighforward.
Once you've created your TestRule implementation, then you need to add the following lines to to your JUnit Test Class:
#Rule
public MyTestRuleImpl conditionalTests;
Remember, the field must be public.
And that's it. Good luck -- as I said, you may have to hack a little, but I believe there's a fair amount explained in the blog post. Otherwise, there should be other information on the internets (or in the JUnit sourc code).
Here's a quick example of a TestRule implementation that doesn't do anything.
public abstract class SimpleRule implements TestRule {
public Statement apply(final Statement base, final Description description) {
return new Statement() {
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (Throwable t) {
t.printStackTrace();
}
}
};
}
}