Mockito - mock library call - java

I have the following structure
public class classAImpl implements classA {
public ClassC getTarget(Classc cObj) {
// library call
RegistryLib.init();
// some more code to construct cObj with more info
return cObj
}
}
// Registry Library Class
Class RegistryLibClass{
public void init() {
ClassD.builder.build();
}
}
My test class is trying to test a method which calls getTarget() method written above. I want to completely avoid executing getTarget() method which I am not been able even after mocking it. So far I have tried the following:
Class Testclass {
#Before
public void setUp() {
Testclass mock = PowerMockito.mock(Testclass.class);
PowerMockito.when(mock.getTarget(cObj)).thenReturn(cObj);
}
private ClassC getTarget(cObj) {
return cObj;
}
}
Any help is appreciated!

Assuming you want to test a method in Class B that calls getTarget from Class A, you would do this,
B b = new B();
A a = Mockito.mock(A.class);
C c = new C();
Mockito.when(a.getTarget(Mockito.any(C.class)).thenReturn(c);
boolean isPresent = b.someMethodToTest();
assertEquals("someMethodToTest was supposed to return true", true/*expected*/, isPresent);
Edit#1
You need to use Powermockito to mock the static method to return nothing as mentioned here
#PrepareForTest(RegistryLibClass.class) //at the top of the class
//inside your test
PowerMockito.mockStatic(RegistryLibClass.class);
Mockito.when(RegistryLibClass.init()).doNothing();

Disclaimer - I'm not that familiar with mockito, but wouldn't you normally mock the class you want to avoid using? Like this:
class Testclass {
#Before
public void setUp() {
//create some mock of expected cObj here to be returned.
classAImpl mock = PowerMockito.mock(classAImpl.class);
PowerMockito.when(
mock.getTarget(cObj.class /*Shouldn't this be class call?*/))
.thenReturn(cObj);
}
}
And then you would inject mock as dependency into the object that uses it and that you want to test.
If I'm wrong then feel free to ignore me, but thats how other mocking libraries I used worked. I'd advise you to go read some tutorials about mocking for tests regardless.
As side note, use of Class and class in names made this example extremely difficult to understand.

Your example is very confusing as you are trying to mock your test class itself instead of the main class.
Also you have mentioned that you are trying to test a method which calls getTarget() method, but I don't see any method in your class that calls getTarget() method.
I have put down a simple example below for your understanding. Let me know if this helps.
ClassA
public class ClassA {
public String method1() {
return "ClassA -> method1";
}
public static String method2() {
return "ClassA -> method2";
}
}
ClassB calls Class A methods
public class ClassB {
public void method1() {
System.out.println("ClassB -> method1");
new ClassA().method1();
ClassA.method2();
}
}
ClassB Test
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassA.class)
public class ClassBTest {
#Mock
ClassA mock;
#Before
public void setUp() throws Exception {
// Initialize mocks
MockitoAnnotations.initMocks(this);
// This is for mocking new objects
PowerMockito.whenNew(ClassA.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.method1()).thenReturn("Mocked Method 1");
// This is for mocking static methods
PowerMockito.mockStatic(ClassA.class);
PowerMockito.when(ClassA.method2()).thenReturn("Mocked Method 2");
}
#Test
public void testMeth() {
System.out.println(new ClassA().method1()); // Prints - Mocked Method 1
System.out.println(ClassA.method2()); // Prints - Mocked Method 2
}
}

Related

How to test a method of a class with constructor arguments using Mockito/Powermock

I have a Mockito/PowerMockito issue!
The class to test is as below :
public class ClassToTest {
private String string;
public ClassToTest(String s) {
this.string = s;
}
public String concatenate() {
return string.concat(" - Done!");
}
public ClassToTest create(String s) {
return new ClassToTest(s);
}
}
The test class i wrote :
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassToTest.class)
public class ClassToTestTest {
#Test
public void concatenate() throws Exception {
ClassToTest classToTest = Mockito.mock(ClassToTest.class);
PowerMockito.whenNew(ClassToTest.class).withArguments(Mockito.anyString()).thenReturn(classToTest);
classToTest.concatenate();
}
}
Question - How do i set a value of the instance variable named "string" from test class so that i can test concatenate method(concatenate method uses the constructor initialized "string" variable") Currently the debug point is not even going inside concatenate() method. I need to do this with either mockito/powermock.
Note - The example I have given is a representation of the issue i am facing in real time.
Any leads would help me.
Thanks in advance!!
Your test is pointless for several reasons.
you mock the class you're trying to test
you mock a method that is not even called in the test
you don't verify the result of the method you call.
Your test can just be
ClassToTest tested = new ClassToTest("test"); // create instance
String concatResult = tested.concatenate(); // call method under test
assertThat(concatResult).isEqualTo("test - Done"); // verify result
No need to mock anything. If you want to test the create method (of which I don't see the point at all btw), you can do
ClassToTest tested = new ClassToTest(""); // the String is never used anyway
ClassToTest created = tested.create("test"); // call method under test
assertThat(created.concatenate()).isEqualTo("test - Done"); // verify
If you mock classes you're testing, you don't test the classes behavior, but only the mocked result. Consider
Don't do this
ClassToTest mock = mock(ClassToTest.class);
ClassToTest other = mock(ClassToTest.class);
when(mock.create(anyString()).thenReturn(other);
when(other.concatenate(anyString()).thenReturn("expected");
ClassToTest created = mock.create("test");
String result = created.concatenate("lala");
assertThat(result).isEqualTo("expected"); // duh

Mocking object instantiation with new in Java using PowerMock not working

I am trying to Unit Test a class in Java.
Code for this class: ToBeTested
public class ToBeTested {
private Collaborator collaborator;
public ToBeTested() {
System.out.println("ToBeTested: Constructor");
}
public void start() {
System.out.println("ToBeTested: Start");
collaborator = new Collaborator();
}
}
This class ToBeTested depends on another class, Collaborator.
Code for class: Collaborator
public class Collaborator {
Collaborator() {
System.out.println("Collaborator: Constructor");
}
}
While testing the class ToBeTested, I want to stub instantiation of Collaborator. That's a dependency I want to mock and I don't want it's constructor to be called.
I'm using Junit (v4.12) and PowerMock (v1.6.1).
Code for Test Class: TestToBeTested
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.annotation.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.powermock.api.easymock.PowerMock.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ToBeTested.class, Collaborator.class})
public class TestToBeTested {
#Mock
private Collaborator collaborator;
private ToBeTested toBeTested;
#Before
public void setUp() throws Exception {
collaborator = createMock(Collaborator.class);
expectNew(collaborator.getClass()).andReturn(null);
toBeTested = new ToBeTested();
}
#Test
public void test() {
replayAll();
toBeTested.start();
verifyAll();
}
}
My understanding is that this will mock or stub out Collaborator and it's constructor should not be called. However, when I run the test, I notice that original constructor of Collaborator is called.
Output of test run:
ToBeTested: Constructor
ToBeTested: Start
Collaborator: Constructor
I'm very new to Java and Unit Testing in Java, so I apologize if I'm doing a very fundamental mistake here.
During my quest to find out the root cause, I have referred to following SO questions:
PowerMock's expectNew() isn't mocking a constructor as expected
PowerMock expectNew how to specify the type of the parameters
Not able to mock constructor using PowerMock
https://dzone.com/articles/using-powermock-mock
Thank you very much in advance for help/suggestions/feedback.
One possible reason that it might not be working could be this line:
expectNew(collaborator.getClass()).andReturn(null);
collaborator is a mocked instance which means it's "getClass()" method is going to return Collaborator$CGLIBMockedWithPowermock or something like that -- not the Collaborator class you want it to be. So you might get it to work simply by changing that line to:
expectNew(Collaborator.class).andReturn(null);

Mock overridden method using mockito powermokito

I want to test my Service class method testB1Method2 by mocking overridden method a1Method2 of class B1. I do not want to change anything in class A1 and B1. I am using mockito 1.9.0 and powermockito 1.4.12. The following code I am trying:
UnitTestService class:
import static org.mockito.Mockito.*;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.testng.Assert;
import org.testng.annotations.Test;
public class UnitTestService {
#Mock
B1 b1;
#InjectMocks
Service service = new Service();
#Test
public void testB1Method2() throws Exception {
MockitoAnnotations.initMocks(this);
when(b1.a1Method2()).thenReturn("mockvalue");
PowerMockito.whenNew(B1.class).withArguments(Mockito.any()).thenReturn(b1);
String output = service.serviceMethod();
System.out.println("=====" + output);
Assert.assertTrue("mockvalue".equalsIgnoreCase(output), "testA1Method2 failed!");
}
}
Service class:
public class Service {
public String serviceMethod() {
B1 b1 = new B1("some data");
return b1.a1Method2();
}
}
class A1:
public abstract class A1 {
public A1(String data) {
//doing many thing with data
}
public String a1Method1() {
return "from a1Method1";
}
public String a1Method2() {
return "from a1Method2";
}
}
B1 class:
public class B1 extends A1 {
public B1(String data) {
super(data);
}
#Override
public String a1Method1() {
return "a1Method1 from B1 class";
}
}
I am running class UnitTestService using testNG in eclipse. And here actual method in class B1 a1Method2 is getting called as it is printing "=====from a1Method2" in console. ie: here it seems mockito is not able to mock this method.
What code change should I make in UnitTestService class to mock class B1 a1Method2 ?
You created hard to test code there, for absolutely no good reason.
What is breaking your neck is that small little call to new B1 in your service class.
If you would be using dependency injection for that object; then you would absolutely not need to deal with powermock and mocking inherited methods. Because then you could simply create a "mock" B1; pass that to your service; and then you have full control over what will be happening during your test.
So, the viable alternative here might be to avoid complex test setup by simply improving your production code to be easier to test.
Watch those videos to better understand what I am talking about!

Powermock : Mocked method still called

First of all, please know that I've searched SO before asking this question, but I was unable to find a satisfying answer.
I'm using JUnit4 and Powermock 1.5.5 (with mockito 1.9.5)
My problem is the following : in my unit tests, I need to mock a static method in a class I can't modify. I only want to mock one method, and not the whole class, so I went for a spy.
Here's what I have so far :
[...]
import static org.mockito.Matchers.*;
import static org.powermock.api.mockito.PowerMockito.*;
#RunWith(JUnitParamsRunner.class)
#ContextConfiguration(locations={"classpath:applicationContext-test.xml"},
loader=MockWebApplicationContextLoader.class)
#MockWebApplication(name="my-app")
#PrepareForTest(value = {
Role.class
})
public class MyTest {
#Rule
public PowerMockRule powerMockRule = new PowerMockRule();
#Before
public void setUp() throws Exception {
initSpring();
mockRoleServices();
}
private void mockRoleServices() throws Exception {
spy(Role.class);
RoleAnswer roleAnswer = new RoleAnswer(RoleEnum.ADMIN);
when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
.then(roleAnswer);
}
private class RoleAnswer implements Answer<Boolean> {
private RoleEnum roleEnum;
private RoleAnswer(RoleEnum roleEnum) {
this.roleEnum = roleEnum;
}
#Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return getRenderRequest().getUserRole() != null &&
getRenderRequest().getUserRole().equals(roleEnum);
}
}
}
Here's the problem : the method Role.hasAdministratorRole() is called instead of being mocked
Here's what I tried so far :
Using mockStatic(Role.class) instead of the spy() method. As expected, all methods are mocked, so I end up getting an NPE before Role.hasAdministratorRole() is called
Doing something like doAnswer(...).when(...). I get a runtime error with powermock telling me my mock is not complete (which actually confirms that something's wrong either with my code or with the lib itself)
Trying to declare the method by its name rather than calling it directly : when(Role.class, "hasAdministratorRole", long.class, long.class, long.class). Same behavior
A bunch of other things I don't recall anymore.
Your help will be greatly appreciated.
Thanks !
EDIT : Thanks to SrikanthLingala's answer, I was able to pinpoint the problem.
This didn't work :
when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
.thenAnswer(roleAnswer);
but this did :
doAnswer(roleAnswer).when(Role.class, "hasSiteAdministratorRole",
anyLong(), anyLong(), anyLong());
So switching then when() and the answer() worked
As I do not have all of your implementations, I setup some dummy implementations and made a similar setup like yours. The below code works fine for me.
import static junit.framework.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(value = {
Role.class
})
public class RoleTest {
#Test
public void mockRoleServices() throws Exception {
PowerMockito.spy(Role.class);
PowerMockito.doAnswer(new RoleAnswer(RoleEnum.ADMIN)).when(Role.class, "hasAdministratorRole", Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
Role.printOut();
assertTrue(Role.hasAdministratorRole(1, 1, 1));
}
private class RoleAnswer implements Answer<Boolean> {
private RoleEnum roleEnum;
private RoleAnswer(RoleEnum roleEnum) {
this.roleEnum = roleEnum;
}
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return true;
}
}
}
Dummy Role class:
public class Role {
public static Boolean hasAdministratorRole(long a, long b, long c) {
System.out.println("Inside hasAdministratorRole");
return a + b + c < 0;
}
public static void printOut() {
System.out.println("Inside Printout");
}
}
My test case does not printout Inside hasAdministratorRole, but prints out Inside Printout
Hope this helps
Glad you have solved your issue, this just a warning for everyone else having a similar issue.
Project setup:
Powermock 1.5.5
Mockito 1.9.5
TestNG 6.8.8
Powermock is not taking into account mocks/spies created in a method annotated with #BeforeTest
E.g.:
#BeforeTest
public void setup(){
testee = mock(AClass.class);
}
It gets discarded and then it is entering the mocked method instead of returning the expected result OR throwing all kinds of strange exceptions. When moved to a common test method, it suddenly starts working:
#Test
public void test(){
AClass testee = mock(AClass.class);
....
}
Possibly it is a bug.

Do Mock objects get reset for each test?

I'm using the Mockito framework to create Mock objects in my JUnit tests. Each mock knows what methods have been called on it, so during my tests I can write
verify(myMock, atLeastOnce()).myMethod();
I am wondering if this internal mock knowledge of what it has called will persist across my tests? If it does persist, then I could be getting false positives when using the same verify method in two tests.
A code example
#RunWith(MockitoJUnitRunner.class)
public class EmrActivitiesImplTest {
#Mock private MyClass myMock;
#Before
public void setup() {
when(myMock.myMethod()).thenReturn("hello");
}
#Test
public void test1() {
// ..some logic
verify(myMock, atLeastOnce()).myMethod();
}
#Test
public void test2() {
// ..some other logic
verify(myMock, atLeastOnce()).myMethod();
}
}
Mock state is persisted - test2 will pass regardless, since test1's verify method passed
Mock state is reset - test2 will fail if myMock.myMethod() isn't called
JUnit creates a new instance of test class each time it runs a new test method and runs #Before method each time it creates a new test class. You can easily test it:
#Before
public void setup() {
System.out.println("setup");
when(myMock.myMethod()).thenReturn("hello");
}
And MockitoJUnitRunner will create a new MyMock mock instance for every test method.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
#RunWith(MockitoJUnitRunner.class)
public class sandbox {
#Mock
private MyClass myMock;
#Before
public void setup() {
when(myMock.myMethod()).thenReturn("hello");
}
#Test
public void test1() {
myMock.myMethod();
verify(myMock, times(1)).myMethod();
}
#Test
public void test2() {
myMock.myMethod();
verify(myMock, times(1)).myMethod();
}
}
This passes. If the state persisted then the second test would fail. If you debug it you would see that you get a new instance of the mocked object for each test.
If you just initialize the Mock objects in your setup, then inside each test you can provide different functionality. You can initialize it once and change how they act/expect per test after that.

Categories