Can we mock a method with powermockito and testng - junit

I am writing a TestNG testcase which extends atgdustcase. I need to mock a method in class B. This class B is injected into class A using properties file in ATG. Class C is a test class for testing functionality of class A. D is a test class which extends AtgDustCase.
#RunWith(PowerMockRunner.class)
#PrepareForTest({A.class, B.class})
Public class c extends D{
#InjectGlobalComponent(Path for component A)
#InjectMocks
private A aClass;
public void testMethod(){
String string = "abc";
Map map = new HashMap();
map.put("a", "c");
aClass = getRequest.resolveName(Component A path);
B b = PowerMockito.mock(B.class);
A a = PowerMockito.spy(new A());
PowerMockito.whenNew(A.class).withNoArguments().thenReturn(a);
a.setB(B);
PowerMockito.when(a.getB()).thenReturn(b);
Mockito.stub(b.getMethodToMock(string)).toReturn(map);
Mockito.verify(b).getMethodToMock(string);
aClass.invokeTestMethod();// This method calls the b.getMethodToMock()
}
}
I need to mock getMethodToMock(). When I execute invokeTestMethod(), this calls getMethodToMock(). At that time, map should be returned. Instead it is executing getMethodToMock() and it is throwing an error(The problem with execution is I need to fetch some records from DB. I need to mock this method and return a map which contains information retrieved from DB). I am not sure whether mocking is happening properly or not, as in debug mode I am able to see that the getMethodToMock() is getting invoked. Please help me how can I mock this method and skip the execution of this method.
Note: I tried using Powermockito, but my testcase is TestNGsuite. I need to run TestNGSuite instead of running it as Junit.

Related

Mocking New Object Call In Superclass

I am having a hard time getting this one piece of mocking figured out for my unit tests. The classes in question are all part of legacy code that I don't really have the option of changing right now (I am hoping to be able to do some refactoring in the future, but need tests now).
Here are the two classes that I am dealing with, and the specific part I am having trouble with. Class A declares an object using new and then class B uses the object. I am trying to mock the object but I keep getting the real version of it instead of the mocked version.
public class B extends A(){
...
int x = problemObj.doMethod();
}
public class A(){
...
ProblemObj problemObj = new ProblemObj();
}
Here is my test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({A.class, B.class})
public class ATest(){
private ProblemObj problemObjMock;
#Before
public void setUp(){
problemObj = PowerMockito.Mock(ProblemObj.class);
}
#Test
public void test(){
PowerMockito.whenNew(ProblemObj.class).withNoArguments().thenReturn(problemObj);
...//rest of test below here
}
}
I have done other whenNew mocking in tests and set it up the same way as this. But for some reason this object being in the superclass is really throwing me off.
Versions used are Junit:4.11, Mockito:1.9.5, Powermock: 1.6.6

Testing constructor when using #Before annotation

I want to test SomeClass methods.
For that, I need SomeClass instance in every test so I'm using #Before annotation and initiate an instance of SomeClass named SC.
The problem is:- How can I test the constructor function after I already use it? It doesn't make sense.
Additional question:- The constructor can get number of arguments and they can influnce the methods outputs, should I mock this class instead of creating an instance of it?
public class SomeClassTest {
SomeClass SC;
#Before
public void initlize() throws IOException{
SC= new SomeClass (argument1,argument2,..);
}
#Test
public void ConstructorTest() {
}
Just don't use the object SC in your ConstructorTest. If you wan't to test a certain outcome from the construction of a SomeClass object with certain parameters then just construct it as such within your ConstructorTest and then assert the relevant outcomes you expect on the newly constructed object.
And no you shouldn't be mocking this class. The test is for testing this class so if you mock it's behaviour then you aren't really testing anything.

Unable to mock URL class using PowerMockito/Mockito

I am trying to use PowerMockito to mock the creation of the java.net.URL class in my code that I'm testing. Basically, I want to prevent the real HTTP request from occurring and instead 1) check the data when the request is made and 2) supply my own test data back on a mocked response. This is what I'm trying:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ URL.class, MockedHttpConnection.class })
public class Test {
URL mockedURL = PowerMockito.mock(URL.class);
MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class);
...
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL);
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
...
}
The code that I want to test looks like this:
URL wlInvokeUrl = new URL(wlInvokeUrlString);
connection = (HttpURLConnection) wlInvokeUrl.openConnection();
Earlier in my test scenario I mock the wlInvokeUrlString to match "MyURLString". I've also tried using various other forms of the whenNew line, trying to inject the mock. No matter what I try, it never intercepts the constructor. All I want to do is "catch" the call to openConnection() and have it return my mocked HTTP connection instead of the real one.
I have mocked other classes ahead of this one in the same script and these are working as expected. Either I need a second pair of eyes (probably true) or there is something unique about the URL class. I did notice that if I use "whenNew(URL.class).withAnyArguments()" and change the "thenReturn" to "thenAnswer" I could get it to trigger. Only problem is I never get the URL call for my code. What I see is an invocation of the 3-argument constructor for URL.class with all nulls for the parameters. Could it be this class is from the Java runtime and is bootstrapped by the test runner? Any help is much appreciated.
It's a common mistake when use PowerMockito.whenNew.
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
From Powermock wiki
So, you need a bit change your test and add to #PrepareForTesta class which create a new instance of URLlike:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ URL.class, MockedHttpConnection.class , ConnectionUser.class})
public class URLTest {
public class URLTest {
private ConnectionUser connectionUser;
#Before
public void setUp() throws Exception {
connectionUser = new ConnectionUser();
}
#Test
public void testName() throws Exception {
URL mockedURL = PowerMockito.mock(URL.class);
MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class);
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL);
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
connectionUser.open();
assertEquals(mockedConnection, connectionUser.getConnection());
}
}
where:
public class ConnectionUser {
private String wlInvokeUrlString = "MyURLString";
private HttpURLConnection connection;
public void open() throws IOException {
URL wlInvokeUrl = new URL(wlInvokeUrlString);
connection = (HttpURLConnection) wlInvokeUrl.openConnection();
}
public HttpURLConnection getConnection() {
return connection;
}
}
I'm not sure the difference between .withParameterTypes(x) and .withArguments(x) but I believe you need to set it up as follows for your code to work. Give it a try and let me know if this doesn't help.
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
PowerMockito.whenNew(URL.class).withArguments(Mockito.anyString()).thenReturn(mockedURL);
The problem is that the arguments of the real call are not matching with the expected in your mock.
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL) will return mockedURL only the call is new URL("MyURLString").
If you change it to:
PowerMockito.whenNew( URL.class ).withParameterTypes( String.class )
.withArguments( org.mockito.Matchers.any( String.class ) ).thenReturn( mockedURL );
It will catch any string passed to the constructor URL(String) (even null) and return your mock.
When you tried
"whenNew(URL.class).withAnyArguments()" and change the "thenReturn" to
"thenAnswer" I could get it to trigger. Only problem is I never get
the URL call for my code. What I see is an invocation of the
3-argument constructor for URL.class with all nulls for the
parameters.
PowerMock will try to mock all constructors (org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing.InvokeStubMethod at line 122) then it calls the first one (with 3 arguments) and mock its answer. But the subsequent calls will return the already mocked one because you told it to mock for any arguments. That's why you see just one call with null, null, null in your Answer.

JUnit 4 API Get Handle to a #Test Method

Using JUnit 4 API, is there a way to get a handle to a method in a test class that are annotated with #Test?
Here's what I am currently doing:
JUnitCore core = new JUnitCore();
Request request = Request.aClass(MyTest.class);
Result result = core.run(request);
if(result.wasSuccessful())
System.out.println("SUCCESS"); // or do something else
This code will run all tests in MyTest. However, what I want is to just specify the test class name at the beginning (MyTest.class) and do following in a loop:
Get next #Test annotated test in the class.
Print details
Run the test (possibly using Request.method(MyTest.class, "myTestMethod")
I can perhaps use reflection to get the method names and check if they are annotated with Test, but wanted to see if the JUnit API already provides this functionality.
You can use TestClass:
public void runTests(Class<?> clazz) {
TestClass testClass = new TestClass(MyTest.class);
List<FrameworkMethod> tests = testClass.getAnnotatedMethods(
Test.class);
for (FrameworkMethod m : tests) {
String methodName = m.getName();
Request request = Request.method(clazz, methodName);
JUnitCore core = new JUnitCore();
Result result = core.run(request);
if (result.wasSuccessful())
System.out.println(m + ": SUCCESS");
}
}
}
Note that this is an inefficient way to run tests, especially if you have class rules or you use #BeforeClass or #AfterClass

jmockit mocked constructor not returning expected value

I am trying to unit test a class where one of its methods returns an instance of a collaborator class: depending on the values of its arguments it either returns a newly created instance, or a saved, previously created instance.
I mock the constructor call in an Expectations and set the result to a value that is a mocked instance of the collaborator. But when I test the method with parameter values that cause it to create a new instance, the mocked constructor, and therefore the method, does not return the expected value.
I have simplified this down to the following:
package com.mfluent;
import junit.framework.TestCase;
import mockit.Expectations;
import mockit.Mocked;
import mockit.Tested;
import org.junit.Assert;
import org.junit.Test;
public class ConstructorTest extends TestCase {
static class Collaborator {
}
static class ClassUnderTest {
Collaborator getCollaborator() {
return new Collaborator();
}
}
#Tested
ClassUnderTest classUnderTest;
#Mocked
Collaborator collaborator;
#Test
public void test() {
new Expectations() {
{
new Collaborator();
result = ConstructorTest.this.collaborator;
}
};
Collaborator collaborator = this.classUnderTest.getCollaborator();
Assert.assertTrue("incorrect collaborator returned", collaborator == this.collaborator);
}
}
Any ideas on why this test fails and how to make it work would br greatly appreciated.
Thanks in advance,
Jim Renkel
Senior Technical Staff
mFluent, Inc. LLC
Change the #Mocked annotation to #Capturing, like this:
#Capturing
Collaborator collaborator;
This allows the test to pass for me.
This is a little bit of voodoo magic, in my opinion, but if you'd like to read more, take a look at Capturing internal instances of mocked types in the JMockit tutorial.
Also see Using JMockit to return actual instance from mocked constructor