How to mock Session object in java - java

I have created a method, in which i am using JaloSession. I am writing a Junit test for this.
Please let me know how can i mock the following.
ABC abc = JaloSession.getCurrentSession.getAttribute("abc");
Thanks in advance.

With powermock you can mock the static call:
mockStatic(JaloSession.class);
expect(JaloSession.getCurrentSession()).andReturn(yourMock);
...etc
However you don't need to do that. Perhaps the easiest thing since you control the code is to wrap this method call in a protected method
protected ABC getAbc(){
return JaloSession.getCurrentSession.getAttribute("abc");
}
And then in your tests, make a subclass of your class that overrides getAbc() to return a different ABC instance.
#Test
public void myTest(){
final ABC mockAbc = ....
Foo foo = new Foo(){
#Override
protected ABC getAbc(){
return mockAbc;
}
};
//do test on Foo
}

You can't (easily) because of the static call.
So either pass the current session in to the function you are testing, or define an interface for getting the current session and pass that to your object's constructor. In production implement it to call the static nmethod, and in test either mock it or build a fake.
As a bonus you will end up with a cleaner design, where dependencies are passed in from above instead of directly accessed at the lowest levels.

With the JMockit mocking library, you can mock it as follows:
#Test
public void mockJaloSession(#Mocked final JaloSession jalo) {
final ABC testABC = new ABC();
new Expectations() {{ jalo.getAttribute("abc"); result = testABC; }};
// From code under test:
ABC abc = JaloSession.getCurrentSession().getAttribute("abc");
assertSame(testABC, abc);
}
(The test doesn't need to worry about the getCurrentSession() call as it will automatically return the mock jalo object.)

Related

Mocking a separate class function from the class that is being tested

I have a function that is calling a method from another class. This class and method have been tested and are using live data which makes my test inconsistent with the expected values I hard coded.
public class MyClass{
public void functionToBeTested(String params){
//stuff to do
Caller call = new Caller();
callResult = call.post(someJSON);
//do stuff with callResult
}
}
Here is the junit:
public class TestMyClass{
MyClass testClass = new MyClass();
Caller mock;
#Before
public void setup(){
premadeAnswer = new String(file);
mock = Mockito.mock(Caller.class);
Mockito.when(mock.post(Mockito.any())).thenReturn(premadeAnswer);
}
#Test
public void studentFees_CorrectSSN(){
assertEquals(expected.getThing(), testClass.functionToBeTested("PARAMS").getThing());
}
}
I was pretty sure I did everything right but obviously its not mocking and instead calling the function ans behaving as expected if it wasn't a junit. If I had to make a guess as to whats happening it would be that even though I am creating a mocked object and using when/thenReturn it is not attached to MyClass testClass object.
That won't work because Caller is not injected into functionToBeTested function.
Mockito.when(mock.post(Mockito.any())).thenReturn(premadeAnswer);
this when statement is working only on your mocked instance, inside functionToBeTested you are creating a new instance of Caller.
Either change functionToBeTested(String params) to functionToBeTested(String params, Caller call) and then pass your mocked Caller instance or try mocking Caller constructor.
More info about second approach here
I noticed in your first block of code that you shared, that there is no return value specified. I added void in the code block below.
public class MyClass{
public void functionToBeTested(String params){
//stuff to do
Caller call = new Caller();
callResult = call.post(someJSON);
//do stuff with callResult
}
}

Not able to mock method which expects interface object

I'm using Mockito with Junit version : 4.8.2
I'm not able to mock methods which expects any interface objects.
For example,
public interface If extends Xyz {
}
Class Abc {
protected List <String> getIPAddress(If x, String n) {
}
}
This is sample test method:
#Test
public void testGetIPAddress() {
Abc mockAbc = mock(Abc.class, CALLS_REAL_METHODS);
when(mockAbc.getIPAddress(any(Xyz.class), anyString())).thenReturn(new List <String>());
}
When I run the above method, I get:
NullPointerException
UPDATES
Actually I found out that the problem is using "CALLS_REAL_METHODS", when instantiating mocked object. Even if I use
when(mockAbc.getIPAddress(any(If.class), anyString())).thenReturn(null);
It is throwing NPE. The reason might be it's still calling the real method.
How do I override calling the real method in this case?
you need to call getIpAdress with an If not an Xyz
Also, new List <String>() won't work, as List is an interface, use new ArrayList<String>() instead:
#Test
public void testGetIPAddress() {
Abc mockAbc = mock(Abc.class, CALLS_REAL_METHODS);
when(mockAbc.getIPAddress(any(If.class), anyString())).thenReturn(new ArrayList<String>());
}

How should I mock out a single method inside an object I'm trying to test?

I have a problem with a class that I am testing where in almost every method I want to test, one of the first things each method does is call this one specific method. This method that is called once by all of these other methods takes a long time to execute. I don't want to have to wait for this every time I run my tests, it really is just a huge waste of time.
I attempted to #Spy the method using Mocktio, but I ran into problems because the really long method doesn't return anything. Can someone suggest a good way to mock out a single method inside a class I am trying to test?
Example:
public class myClass {
public void methodOne() {
reallyLongMethod();
// More code
}
public void methodTwo() {
reallyLongMethod();
// More code
}
.
.
.
public void methodN() {
reallyLongMethod();
// More code
}
public void reallyLongMethod() {
}
}
This is the class I am trying to test. I want to test all of the 'methodX()' methods. I don't want to run reallyLongMethod everysingle time however.
So, is there a way to use Mockito 'Spy' to stub out reallyLongMethod()? Even though it doesn'treturn anything?
You can use a Spy with doNothing(), but make sure you use the spy during the test. Mockito spies copy the original, instead of delegating to it.
#RunWith(MockitoJUnitRunner.class)
public class YourTest {
// Option 1:
// #Spy MyClass myClass = new MyClass();
// Option 2 (see #Before method)
MyClass myClass;
#Before public void ignoreReallyLongMethod() {
myClass = spy(new MyClass()); // discard original
doNothing().when(myClass).reallyLongMethod();
}
#Test public void methodOneWorks() {
myClass.methodOne(); // you're using the spy here
assertEquals(42, myClass.getFoo());
}
}
Though this does evoke a code smell, don't mock or stub the class under test, as long as you're careful to test the method behavior (methodOne) and not the stubbed behavior (reallyLongMethod) you'll be good to go. If you do want to test reallyLongMethod you'll want to use a different object instance or else you'll "test" the doNothing() call alone. Do bear in mind that if reallyLongMethod and your other methods have any negative interactions, these tests won't tell you about that.
By the way, you can also do the equivalent without using Mockito, which may make a little clearer what you are or aren't doing with your mocks:
#RunWith(JUnit4.class)
public class YourTest {
MyClass myClass;
#Before public void createMyClass() {
myClass = new MyClass() { // create an anonymous inner class
#Override public void reallyLongMethod() {} // that does nothing here
};
}
}

Invoking a private method via JMockit to test result

Am using JMockit 1.1 and all I want to do is invoke a private method and test the return value. However, I am having trouble understanding exactly how to do this from the JMockit De-Encapsulation example.
The method I am trying to test is the private method in this class:
public class StringToTransaction {
private List<String> parseTransactionString(final String input) {
// .. processing
return resultList;
}
}
And my test code is below.
#Test
public void testParsingForCommas() {
final StringToTransaction tested = new StringToTransaction();
final List<String> expected = new ArrayList<String>();
// Add expected strings list here..
new Expectations() {
{
invoke(tested, "parseTransactionString", "blah blah");
returns(expected);
}
};
}
And the error I am getting is:
java.lang.IllegalStateException: Missing invocation to mocked type at
this point; please make sure such invocations appear only after the
declaration of a suitable mock field or parameter
Perhaps I have misunderstood the whole API here, because I don't think I want to mock the class.. just test the result of calling the private method.
I think you are making this too complicated. You should not be using the Expectations block at all. All you need to do is something like this:
#Test
public void testParsingForCommas() {
StringToTransaction tested = new StringToTransaction();
List<String> expected = new ArrayList<String>();
// Add expected strings list here..
List<String> actual = Deencapsulation.invoke(tested, "parseTransactionString", "blah blah");
assertEquals(expected, actual);
}
Basically, call a private method via Deencapsulation and test that the actual is equal to the expected. Just like you would if the method were public. No mocking is being done, so no Expectations block is needed.
At this point, I don't know if JMockit can or should be used for this. Testing my private method can be done with plain old reflection, although I started this exercise to learn about JMockit (and test my code). In case JMockit cannot be used for this, here is how I can use reflection instead.
#Test
public void testParsingForCommas() throws Exception {
StringToTransaction tested = new StringToTransaction();
ArrayList<String> expected = new ArrayList<>();
expected.add("Test");
Method declaredMethod =
tested.getClass().getDeclaredMethod("parseTransactionString",
String.class);
declaredMethod.setAccessible(true);
Object actual = declaredMethod.invoke(tested, "blah blah");
assertEquals(expected, actual);
}
The call to setAccessible(true) is important here or the invoke will blow up when calling a private method.
declaredMethod.setAccessible(true);
But you want to know what is really cool? If you don't call setAccessible(true), it will blow up with a java.lang.StackOverflowError! :)
As mocking private methods is not allowed in latest Jmockit. One can mock the APIs used inside that private method as a Workaround instead of mocking the private method.
This workaround can also be treated as a final solution.
Example:
Actual Class:
class A {
private int getId(String name){ //private method
return DAOManager.getDao().getId(name); //Call to non-private method can be mocked.
}
}
Test Class:
public class ATest{
#Before
public void setUp(){
new MockDAOManager();
}
//Mock APIs used by the private method `getId`.
public static class MockDAOManager extends MockUp<MockDAOManager>{
static mocked_user_id = 101;
#Mock
public DAOManager getDao() throws Exception{
return new DAOManager();
}
#Mock
public Integer getId(String name){
return mocked_user_id;
}
}
}
Note:
If you don't have such logic(private method calls to another non-private
method) then you may have to refactor your code, Otherwise this will
not work.
Here DAOManager.getDao().getId(name) is not a private API.
There may be a need to mock all APIs used by that private method.
start from 1.35(?) jmockit removed that helper method. for reasons that it is no longer useful (which I don't quite understand)
but yes, this utility is available somewhere else
org.springframework.test.util.ReflectionTestUtils
As mentioned by #Jeff Olson, you can also call the private methods of a bean by declaring them #Tested.
Here is an example:
// Java
#Tested
private YourServiceImplClass serviceImpl;
#Test
public void testPrivateMethod() {
List<String> expected = new ArrayList<String>();
// Add expected strings list here..
List<String> actual = Deencapsulation.invoke(serviceImpl, "yourPrivateMethod", "arguments");
assertEquals(expected, actual);
}
Why do you want to test the private method directly ? Most of the times API methods i.e. public interface methods are unit tested as private methods will be be indirectly tested as well along with them. You can put assert statements with expected values from private methods where you call them within the public methods. So if assert fails you are sure that there is some issue with the private method. So you need not test it separately.

Mocking static method that is called multiple times

I have a static method, that is used in multiple places, mostly in static initialization block. It takes a Class object as parameter, and returns the class's instance.
I want to mock this static method only when particular Class object is used as parameter. But when the method is called from other places, with different Class objects, it returns null.
How can we have the static method execute actual implementation in case of parameters other than the mocked one?
class ABC{
void someMethod(){
Node impl = ServiceFactory.getImpl(Node.class); //need to mock this call
impl.xyz();
}
}
class SomeOtherClass{
static Line impl = ServiceFactory.getImpl(Line.class); //the mock code below returns null here
}
class TestABC{
#Mocked ServiceFactory fact;
#Test
public void testSomeMethod(){
new NonStrictExpectations(){
ServiceFactory.getImpl(Node.class);
returns(new NodeImpl());
}
}
}
What you want is a form of "partial mocking", specifically dynamic partial mocking in the JMockit API:
#Test
public void testSomeMethod() {
new NonStrictExpectations(ServiceFactory.class) {{
ServiceFactory.getImpl(Node.class); result = new NodeImpl();
}};
// Call tested code...
}
Only the invocations that match a recorded expectation will get mocked. Others will execute the real implementation, when the dynamically mocked class is called.

Categories

Resources