How to Mock Static calls of external Jar - java

I am trying to mock the static calls of external jar. But the real method is getting calling . Can anyone help me. Thanks in advance
Method :
public void method(){
try{
OutputClass output = StaticClass.getName("String","String");
}catch(Eception e){
e.printStackTrace();
}
}
Note : StaticClassOutput and OutputClass are frrom external jar.
I tried by using MockStatic also(Used Mockito inline 5.1.1 dependency). but it didnt work out..Original getName method is getting called. I want to mock the getName and return mock "OutputClass".
Tried solution :
try(MockStatic<StaticClass> mockStatic = Mockito.mockStatic(StaticClass.Class)){
OutputClass output = Mockito.mock(OutputClass.Class);
mockStatic.when(()->StaticClass.getName(Mockito.anyString(),Mockito.anyString())).thenReturn(output);
}
This code is not working-getName real method is calling . Please help.

Related

Running JUnitCore with instances instead of classes

I'm looking to run JUnit 4.12+ programmatically, and a cursory search for doing so yielded (amongst many other similar posts) this answer, which prescribes the following basic solution:
#RunWith(Suite)
#Suite.SuiteClasses ({
MyTestClass1.class,
MyTestClass2.class
})
public class MyTestSuite {
}
Result testResults = JUnitCore.runClasses(MyTestSuite.class);
...and I was able to get this working, no sweat. So far so good!
Problem is: I have some pretty sophisticated test classes that need to be instantiated/injected with very specific properties at runtime...not something that can be done from inside a no-arg constructor. But the above method (specifying to just run any old instance of a set of classes) doesn't allow you to instantiate your test classes, configure them, and then run them.
Is there a way to do this? I couldn't find anything looking at the JUnit API. I am looking for something like:
MyTestClass1 mtc1 = new MyTestClass1(...);
MyTestClass2 mtc2 = new MyTestClass2(...);
Result testResults = JUnitCore.run(mtc1, mtc2);
You probably need custom runner to achieve that. Junit 4/5 comes with third party runner that can perform dependency Injection for Constructors and Methods. Few runner which are pretty popular are Mockito(MockitoJUnitRunner) and SpringJUnit4ClassRunner in case you are using Spring. You can check out custom runner and implementation details at:
https://github.com/junit-team/junit4/wiki/Custom-runners
I got this working with a custom Runner with sample (Groovy pseudo-code) as follows:
class MyRunner extends Runner {
#Override
Description getDescription() {
return null
}
#Override
void run(RunNotifier notifier) {
// LoginTests.class is a test class I want to run
LoginTests loginTests = new LoginTests(<my args here>)
Description description = Description.createSuiteDescription(LoginTests)
notifier.fireTestStarted(description)
try {
log.info("About to doSomething()...")
loginTests.doSomething()
log.info("Did it...")
notifier.fireTestFinished(description)
} catch(Throwable throwable) {
log.info("doSomething() failed...")
notifier.fireTestAssumptionFailed(new Failure(description, throwable))
}
}
}
Result testResults = new JUnitCore().run(Request.runner(new MyRunner()))

Suppress static block

Programming Language : Java
Testing tool : powermockito,Junit
I have a static block in my code. I am using that code particle as several reference. While during integration testing (using powermockito) I mocked a getWebDetails() method in the below example. The method for mocking (getWebDetails) is also getting called from the static block in my program, so it excecutes before my test gets excecuted and returns a null value. I need to assign values to xml contents during my testing.
class test1{
private static String xmlcontents;
static {
xmlcontents= ServiceUtils.getWebDetails();
}
public static String getWebDetails() throws Exception{
url = test2.getURL();
return url;
}
}
Nota bene (please note): I tried using #SuppressStaticInitializationFor("test1"), but it suppresses all the static methods inside the class.
Can anyone help me? Any help will be highly appreciable..

Java Unit testing path matching

I am trying to understand Unit testing and how the correct classes are being fetched on test time,
I'm having a hard time understanding exactly what is going on behind the scenes and how safe/correct my usages for this are.
This is a very simple example of what i am trying to do, i wrote it here inline so it probably contains some errors, please try to ignore them, as stupid as they may be.
A very simple project directory:
ba/src/main/java/utils/BaUtils.java
ba/test/main/java/utils/BaUtilsTest.java
notBa/src/main/java/im/BaObj.java
BaUtils.java code:
package com.ba.utils;
import notBa.im.BaObj;
public class BaUtils{
public String doSomething(BaObj obj){
obj.doSomething();
}
}
I would like to test BaUtils wihtout actually calling doSomething, and i can't change anything on BaObj class or notBa package. I know that i can (by 'can' i mean it will work) add a new java file to 'ba' project (ba/test/java/notBa/main/java/im/BaObj.java) that will have the same package as the original BaObj, and at runtime the test will import this one instead of the real one, so BaUtils code is tested but BaObj code is not excecuted.
that should look something like like :
package notBa.im.Baobj
public class BaObj{
public void doSomething(){
System.out.println("Did something");
}
}
My questions are (And thank you for reaching this far):
How does this work (Reading references would be great).
Is this kind of test building considered 'good' or 'safe' ?
Thanks!
The solution is to use a mocking framework (I for myself like Mockito).
The test would look like this:
class BlaUtilTes{
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Mock
Blaobj blaobj;
#Test
public void doSomething_WithMockedBlaobj_callsDosomethingOnBlaobj(){
// arrange
BlaUtil blaUtil= new BlaUtil();
// act
blaUtil.doSomething(blaobj);
// assert
Mockito.verify(blaobj).doSomething();
}
}
find more information here http://www.vogella.com/tutorials/Mockito/article.html#testing-with-mock-objects
Your BaUtilsTest class should look like this.. I have used mockito for for mocking external dependencies. Also I changed the method return type to String for easy understanding.
#RunWith(MockitoJUnitRunner.class)
class BaUtilsTest {
BaUtils util;
#Mock
BaObj mockBaObj;
#Before
public void setup() {
util = new BaUtils();
}
#Test
public void testDoSomething() {
Mockito.when(mockBaObj.doSomething()).thenReturn("did the work using mock");
String result = util.doSomething(mockBaObj);
Assert.assertEquals("did the work using mock", result);
}
}

powerMockito mock File objects

I have problem mock whenNew(File.class) using PowerMockito. Here is my method I want to test:
public void foo() {
File tmpFile = new File("Folder");
if (!tmpFile.exists()) {
if (!configFolder.mkdir()) {
throw new RuntimeException("Can't create folder");
}
}
File oneFileInFolder = new File(tmpFile, "fileOne.txt");
if (oneFileInFolder.exists()){
//do something
}
}
Here is test code I wrote:
static File mockFile;
#Before
public void setUp() throws Exception {
//....some code
mockFolder = mock(File.class);
when(mockFolder.getPath()).thenReturn("Folder");
when(mockFolder.exists()).thenReturn(true);
whenNew(File.class).withParameterTypes(String.class).withArguments(anyString()).thenReturn(mockFolder);
//...some code
}
But when I debug my testcase, I still see a real folder created in my pwd. I don't want folders created when I run my testcases. Any idea?
Since you haven't specified this in your question, the following may be missing:
#PrepareForTest(ClassYoureCreatingTheFileInstanceIn.class)
According to the Wiki:
Note that you must prepare the class creating the new instance of MyClass for test, not the MyClass itself. E.g. if the class doing new MyClass() is called X then you'd have to do #PrepareForTest(X.class) in order for whenNew to work.
In other words, X is the class that contains foo() in your example.

Using Mockito / PowerMock to verify a log has been written

I have a class which writes messages to some logs. The class is a utility which doesn't do anything else, it runs in the background, checks a few things and logs them. I'm wondering if it's possible for me to verify in a unit test that the log has been written to without caring about what it is actually writing. Here's my class being tested:
//imports...
public class MyClass {
private static Log log = LogFactory.getLog(MyClass.class);
public MyClass() {
log.info("MyClass is being created.");
}
public void doThing() {
if( everything_is_fine ) {
log.info("This is a message to say everything is fine.");
} else {
log.error("Uh oh...");
}
}
}
And my tester class:
// imports ...
#RunWith(PowerMockRunner.class)
#PrepareForTest({MyClass.class,LogFactory.class})
public class MyClassTest {
Log mockLog;
#Before
public void setup() {
PowerMockito.mockStatic(LogFactory.class);
mockLog = mock(Log.class);
PowerMockito.when(LogFactory.getLog(MyClass.class)).thenReturn(mockLog);
}
#Test
public void test_everything_is_ok() {
MyClass mything = new MyClass(); // should write to log.info
mything.doThing(); // should write to log.info
verify(mockLog, atLeastOnce()).info(anyString());
verify(mockLog, never()).error(anyString());
}
#Test
public void test_everything_is_not_ok() {
MyClass mything = new MyClass(); // should write to log.info
// do something which makes things not ok
mything.doThing(); // should write to log.error
verify(mockLog, atLeastOnce()).info(anyString());
verify(mockLog, atLeastOnce()).error(anyString());
}
}
When I run the tests, I expect that the log.info() is invoked for both tests, and the log.error() is invoked only for the second. However I'm getting a "Wanted but not invoked" for the log.info for both tests. and for log.error on the second. So either:
1) My code is broken and not writing to the log, or
2) My test is broken.
I'm thinking that I've messed up something in my test, probably something really obvious, so has anyone had experience testing something like this who could help me out? Any and all help will be appreciated.
UPDATE:
Thanks to those who helped out, I've got a solution now.
After playing around with the code for a bit, I discovered that there seems to be an issue with the initialization of the log. Doing private static Log log = LogFactory.getLog(MyClass.class); didn't seem to use the mock correctly, so if I move it to the constructor it seemed to be mocked OK and my tests all work as expected:
public class MyClass {
private static Log log;
public MyClass() {
MyClass.log = LogFactory.getLog(MyClass.class);
log.info("MyClass is being created.");
}
// etc ...
}
I've got it working now, but can anyone explain why initializing the log the first way didn't work? Or perhaps point me to somewhere which explains it? I'm not sure if there's a gap in my understanding of how Java initializes objects or if it's a limitation of mocking frameworks.
You can make an abstraction over the Logger like we did here in our project:
https://github.com/4finance/uptodate-gradle-plugin/blob/master/src/main/groovy/com/ofg/uptodate/LoggerProxy.groovy
Then you have to constructors
https://github.com/4finance/uptodate-gradle-plugin/blob/master/src/main/groovy/com/ofg/uptodate/UptodatePlugin.groovy
One with LoggerProxy initialized and one for tests where you can mock it out and verify if proper text was passed. No need for dirty hacks ;)
Since I had the same problem (private static Log log = LogFactory.getLog(MyClass.class);), I'm posting what I did to solve it.
Instead of modifying logger initialization (I was limited by coding rules) I simply split test in different classes...

Categories