my problem is that my unit test are slow because I'm publishing in a topic in those unit test, I would like to mock or change its behavior in some way. I was thinking in use reflection for this class and change the method behavior but I'm not sure if that is possible.
This is the behavior that I like to mock or change:
TopicCall.builder()
.toTopic(XXXX)
.withAttribute(XXXXXX, XXXXX)
.withAttribute(XXXXX, XXXXXX)
.withAttribute(XXXXX,XXXXX)
.publish();
I would like to do this because publis() is a real invocation and the test is slow and causing some problems in jenkins, because several unit test are publishing at the same time.
The Topic class is a public class with a static builder method which return a class instance, just like the next one:
public static TopicCall builder() {
return new TopicCall();
}
My problem is that I just acceding the method of this class from outside and I'm not sending the class in the constructor as example and I'm not able to mock its behavior, I'm not able to modify the TopicCall class because it is a .class utility from a jar, besides that I'm not able to use PowerMockito or another library, just Mockito, is there any way to achieve that?
Thanks!
Disclaimer: I missed the fact that PowerMock is forbidden for the author, but the answer could be useful for other users with the same problem.
PowerMock
As far as you want to mock a static method, then Mockito is not the solution.
This could be done using PowerMock.
PowerMock uses ClassLoader way for mocking, which could significantly increase tests time to run.
Here is an examle on Baeldung how to mock static methods.
Solution scratch:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ TopicCall.class })
public class Test {
#Test
void test() {
mockStatic(TopicCall.class);
when(TopicCall.builder()).thenReturn(/*value to be returned*/ null);
// the test code...
}
}
I want to mock a dependency and return a default value in most test cases since most of them should not care about the values returned but there are some certain cases like I would like to test like the dependency returns some weird values or just throw. So I am modeling it in this way. Most cases, it should return a nice and valid value.
Test Setup which return the 20L by default for all test classes.
Dependency dependency = Mockito.mock(Dependency.class);
when(dependency.returnSomeVal()).thenReturn(20L);
In a specific test cases class, I would like to override the behavior like below:
when(dependency.returnSomeVal()).thenThrow(); //failure cases
when(dependency.returnSomeVal()).thenReturn(Weird_Val); //failure cases
But I don't find a good solution to override the existing behavior? Any idea?
You can reset the mock and add behavior. In the test, do
Mockito.reset(dependency);
when(dependency.returnSomeVal()).thenThrow(); //failure cases
when(dependency.returnSomeVal()).thenReturn(Weird_Val); //failure cases
Resetting will remove all mocked behavior on this class though. If you want to remock only some methods, then you have to create the mock from scratch.
I ended using myself this pattern to mock a bunch of methods of a class providing configurations.
In a #Before method I setup a bunch of stubs for a mocked object that provide a correct configuration for each test. Afterwards, in each test it was extremely convenient to only override one of those stubs to provide a different configuration and test a different error case.
I think the response from Hari Menon is correct but it somehow defeats the purpose explained in the question. If the mock is reset, all the stubs would need to be added again, making this pattern very confusing (it would be better to not use any overriding than using reset in this case, the code would be way more straightforward).
The comments added to the question provide indeed an indirect answer on how to achieve this, and why it works, but it took me a bit to get it working.
In spite of one of the comments, I made everything work by using in my #Before fixture when().thenReturn() and overriding the concrete stub with doReturn().when()
Example:
public class WorkerTest {
private ConfigProvider mockedConfigProvider = mock(ConfigProvider.class);
#Before
public void setup() {
// Setup stubs with a correct config
when(mockedConfigProvider.getValue("property1")).thenReturn("value1");
when(mockedConfigProvider.getValue("property2")).thenReturn("value2");
when(mockedConfigProvider.getValue("property3")).thenReturn("value3");
when(mockedConfigProvider.getValue("property4")).thenReturn("value4");
}
#Test
public void test_GoodConfig(){
// The config object gets injected in the test worker
Worker testWorker = new Worker(mockedConfigProvider);
// testWorker.execute() returns true if everything went well
assertTrue(testWorker.execute());
}
#Test
public void test_BadConfigProp1(){
// Test now with a broken 'property1', overriding that stub.
doReturn(null).when(mockedConfigProvider).getValue("property1");
Worker testWorker = new Worker(mockedConfigProvider);
// testWorker.execute() returns false if there is a problem.
assertFalse(testWorker.execute());
}
#Test
public void test_BadConfigProp2(){
// This test needs to only override the result of property2
doReturn("crazy result").when(mockedConfigProvider).getValue("property2");
...
}
So I started writing tests for our Java-Spring-project.
What I use is JUnit and Mockito. It's said, that when I use the when()...thenReturn() option I can mock services, without simulating them or so. So what I want to do is, to set:
when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)
But no matter which when-clause I do, I always get a NullpointerException, which of course makes sense, because input is null.
Also when I try to mock another method from an object:
when(object.method()).thenReturn(true)
There I also get a Nullpointer, because the method needs a variable, which isn't set.
But I want to use when()..thenReturn() to get around creating this variable and so on. I just want to make sure, that if any class calls this method, then no matter what, just return true or the list above.
Is it a basically misunderstanding from my side, or is there something else wrong?
Code:
public class classIWantToTest implements classIWantToTestFacade{
#Autowired
private SomeService myService;
#Override
public Optional<OutputData> getInformations(final InputData inputData) {
final Optional<OutputData> data = myService.getListWithData(inputData);
if (data.isPresent()) {
final List<ItemData> allData = data.get().getItemDatas();
//do something with the data and allData
return data;
}
return Optional.absent();
}
}
And here is my test class:
public class Test {
private InputData inputdata;
private ClassUnderTest classUnderTest;
final List<ItemData> allData = new ArrayList<ItemData>();
#Mock
private DeliveryItemData item1;
#Mock
private DeliveryItemData item2;
#Mock
private SomeService myService;
#Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
myService = mock(myService.class);
classUnderTest.setService(myService);
item1 = mock(DeliveryItemData.class);
item2 = mock(DeliveryItemData.class);
}
#Test
public void test_sort() {
createData();
when(myService.getListWithData(inputdata).get().getItemDatas());
when(item1.hasSomething()).thenReturn(true);
when(item2.hasSomething()).thenReturn(false);
}
public void createData() {
item1.setSomeValue("val");
item2.setSomeOtherValue("test");
item2.setSomeValue("val");
item2.setSomeOtherValue("value");
allData.add(item1);
allData.add(item2);
}
I had this issue and my problem was that I was calling my method with any() instead of anyInt(). So I had:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())
and I had to change it to:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())
I have no idea why that produced a NullPointerException. Maybe this will help the next poor soul.
The default return value of methods you haven't stubbed yet is false for boolean methods, an empty collection or map for methods returning collections or maps and null otherwise.
This also applies to method calls within when(...). In you're example when(myService.getListWithData(inputData).get()) will cause a NullPointerException because myService.getListWithData(inputData) is null - it has not been stubbed before.
One option is create mocks for all intermediate return values and stub them before use. For example:
ListWithData listWithData = mock(ListWithData.class);
when(listWithData.get()).thenReturn(item1);
when(myService.getListWithData()).thenReturn(listWithData);
Or alternatively, you can specify a different default answer when creating a mock, to make methods return a new mock instead of null: RETURNS_DEEP_STUBS
SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS);
when(myService.getListWithData().get()).thenReturn(item1);
You should read the Javadoc of Mockito.RETURNS_DEEP_STUBS which explains this in more detail and also has some warnings about its usage.
I hope this helps. Just note that your example code seems to have more issues, such as missing assert or verify statements and calling setters on mocks (which does not have any effect).
I had the same problem and my issue was simply that I had not annotated the class properly using #RunWith. In your example, make sure that you have:
#RunWith(MockitoJUnitRunner.class)
public class Test {
...
Once I did that, the NullPointerExceptions disappeared.
For future readers, another cause for NPE when using mocks is forgetting to initialize the mocks like so:
#Mock
SomeMock someMock;
#InjectMocks
SomeService someService;
#Before
public void setup(){
MockitoAnnotations.initMocks(this); //without this you will get NPE
}
#Test
public void someTest(){
Mockito.when(someMock.someMethod()).thenReturn("some result");
// ...
}
Also make sure you are using JUnit for all annotations.
I once accidently created a test with #Test from testNG so the #Before didn't work with it (in testNG the annotation is #BeforeTest)
For me the reason I was getting NPE is that I was using Mockito.any() when mocking primitives. I found that by switching to using the correct variant from mockito gets rid of the errors.
For example, to mock a function that takes a primitive long as parameter, instead of using any(), you should be more specific and replace that with any(Long.class) or Mockito.anyLong().
Hope that helps someone.
As this is the closest I found to the issue I had, it's the first result that comes up and I didn't find an appropriate answer, I'll post the solution here for any future poor souls:
any() doesn't work where mocked class method uses a primitive parameter.
public Boolean getResult(String identifier, boolean switch)
The above will produce the same exact issue as OP.
Solution, just wrap it:
public Boolean getResult(String identifier, Boolean switch)
The latter solves the NPE.
keep in mind if you choose this approach, now you might want to include a nullcheck for Boolean in production code (credit: brought up by Ridcully)
Make sure you initialize your mocks.
JUnit4 use #Before
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
JUnit5 use #BeforeEach
#BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
For JUnit5 check, you are using proper imports also.
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
Corner case:
If you're using Scala and you try to create an any matcher on a value class, you'll get an unhelpful NPE.
So given case class ValueClass(value: Int) extends AnyVal, what you want to do is ValueClass(anyInt) instead of any[ValueClass]
when(mock.someMethod(ValueClass(anyInt))).thenAnswer {
...
val v = ValueClass(invocation.getArguments()(0).asInstanceOf[Int])
...
}
This other SO question is more specifically about that, but you'd miss it when you don't know the issue is with value classes.
For JUnit 5 the test class has to be annotated with:
#ExtendWith(MockitoExtension.class)
imports:
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
My issue was fixed with this addition.
you need to initialize MockitoAnnotations.initMocks(this) method has to called to initialize annotated fields.
#Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
for more details see Doc
Check that the method signature is not declared as final
This one catches out a lot of people who work on codebases which are subjected to Checkstyle and have internalised the need to mark members as final.
i.e. in the OP's example:
object.method()
Make sure that method() is not declared as final:
public final Object method() {
}
Mockito cannot mock a final method and this will come up as a wrapped NPE:
Suppressed: org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Buried deep in the error message is the following:
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
None of the above answers helped me. I was struggling to understand why code works in Java but not in Kotlin.
Then I figured it out from this thread.
You have to make class and member functions open, otherwise NPE was being thrown.
After making function open tests started to pass.
You might as well consider using compiler's "all-open" plugin:
Kotlin has classes and their members final by default, which makes it inconvenient to use frameworks and libraries such as Spring AOP that require classes to be open. The all-open compiler plugin adapts Kotlin to the requirements of those frameworks and makes classes annotated with a specific annotation and their members open without the explicit open keyword.
For me, it was because I was stubbing the mock in the #BeforeAll method.
MockitoExtension does not have a callback for #BeforeAll.
public class MockitoExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver
I moved the stubbing inside the test method it worked!!
In my case, it was the wrong import for when().
I used import static reactor.core.publisher.Mono.when by accident.
In my case, Intellij created Test with org.junit.jupiter.api.Test (Junit5) instead of import org.junit.Test of (Junit4) which caused all beans to be null apparently.
also, make sure the class and test method is public
In my case, my Mockito annotation didn't match the JUnit Version.
When using #ExtendWith(MockitoExtension.class) make sure you're using JUnit 5: import org.junit.jupiter.api.Test;
When using #RunWith(MockitoJUnitRunner.class) make sure you're using JUnit 4: import org.junit.Test;
In my case, I missed add first
PowerMockito.spy(ClassWhichNeedToBeStaticMocked.class);
so this can be helpful to somebody who see such error
java.lang.NullPointerException
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:42)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:112)
#RunWith(MockitoJUnitRunner.class) //(OR) PowerMockRunner.class
#PrepareForTest({UpdateUtil.class,Log.class,SharedPreferences.class,SharedPreferences.Editor.class})
public class InstallationTest extends TestCase{
#Mock
Context mockContext;
#Mock
SharedPreferences mSharedPreferences;
#Mock
SharedPreferences.Editor mSharedPreferenceEdtor;
#Before
public void setUp() throws Exception
{
// mockContext = Mockito.mock(Context.class);
// mSharedPreferences = Mockito.mock(SharedPreferences.class);
// mSharedPreferenceEdtor = Mockito.mock(SharedPreferences.Editor.class);
when(mockContext.getSharedPreferences(Mockito.anyString(),Mockito.anyInt())).thenReturn(mSharedPreferences);
when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.remove(Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.putString(Mockito.anyString(),Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
}
#Test
public void deletePreferencesTest() throws Exception {
}
}
All the above commented codes are not required
{ mockContext = Mockito.mock(Context.class); },
if you use #Mock Annotation to Context mockContext;
#Mock
Context mockContext;
But it will work if you use #RunWith(MockitoJUnitRunner.class) only. As per Mockito you can create mock object by either using #Mock or Mockito.mock(Context.class); ,
I got NullpointerException because of using #RunWith(PowerMockRunner.class), instead of that I changed to #RunWith(MockitoJUnitRunner.class) it works fine
Well in my case it was because of wrong annotation usage. I was using junit 4 for testing and used #BeforeEach instead of #Before while initializing.
Changed it to #Before and it works like charm.
This is where google took me when I had the same NullPointerException with Junit 5, but was correctly using #ExtendWith(MockitoExtension.class) in my maven project.
Turns out I hadn't included the maven-surefire-plugin in my pom.xml and that meant the #ExtendWith wasn't actually doing anything!
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
...
I was using wrong annotation/import of Mock, so my object was not getting formed.
I was using org.evosuite.shaded.org.mockito.Mock and I switched back to org.mockito.Mock. Then as if by magic, it started working for me.
Ed Webb's answer helped in my case. And instead, you can also try add
#Rule public Mocks mocks = new Mocks(this);
if you #RunWith(JUnit4.class).
None of these answers worked for me. This answer doesn't solve OP's issue but since this post is the only one that shows up on googling this issue, I'm sharing my answer here.
I came across this issue while writing unit tests for Android. The issue was that the activity that I was testing extended AppCompatActivity instead of Activity. To fix this, I was able to just replace AppCompatActivity with Activity since I didn't really need it. This might not be a viable solution for everyone, but hopefully knowing the root cause will help someone.
When using JUnit 5 or above. You have to inject the class annotated with #Mock
in an #BeforeEach setup.
In my case it was due to wrong import of the #Test annotation
Make sure you are using the following import
import org.junit.jupiter.api.Test;
Annotate the test class with: #ExtendWith(MockitoExtension.class).
In my case a tested method called another method as a parameter:
Mockito.`when`(repository.getItems(prefs.getUser().id)).thenReturn(listOf())`
While repository is mocked, prefs.getUser().id) will throw NPE. So, first we should mock a parameter, for instance,
Mockito.`when`(prefs.getUser()).thenReturn(User(id = 1, name = "user"))`
Also we should mock prefs. I didn't check it and changed a library, sorry.
I was trying to mock a "final" method, which apparently was the problem.
The right way to handle this would be to use an interface and mock that interface however I couldn't control the library where the "final" method was.
Mockito 2 can handle mocking final method. Add a text file to the project's src/test/resources/mockito-extensions directory named org.mockito.plugins.MockMaker and add a single line of text:
mock-maker-inline
After that, mocking the final method should work just fine.
Check which version of Junit you are using. In the Maven/Gradle build tool, if you set to use testRuntimeOnly 'junit5',then it might not take #RunWith since it is not available and it is replaced with #ExtendWith in Junit5.
This doesnt answer the OP's original query, but its here to try help others with Mockito null pointer exceptions (NPE).
My NPE was happening as I did not explicitly set the class under tests' dependencies to be the classes I had mocked. So the class under test was unable to find its required dependencies, creating the NPE. I tend to not mock the class under test (i.e. use new keyword), to ensure im getting my native class behaviour for testing.
Im still using Junit 4 for reasons outside my control. Worked example;
ClassUnderTest
public class ClassUnderTest {
private DependantClassOne dependantClassOne;
private DependantClassTwo dependantClassTwo;
// remaining class, including setters
}
Test Class
#RunWith(MockitoJUnitRunner.class)
public class Test {
private ClassUnderTest classUnderTest;
private DependantClassOne dependantClassOne;
private DependantClassTwo dependantClassTwo;
#Before
public void setup() {
dependantClassOne = mock(DependantClassOne.class);
dependantClassTwo = mock(DependantClassTwo.class);
classUnderTest = new ClassUnderTest();
classUnderTest.setDependantClassOne(dependantClassOne); //added to prevent NPE
classUnderTest.setDependantClassTwo(dependantClassTwo); //added to prevent NPE
}
// tests
}
I have a code somewhat like this below:
Class A {
public boolean myMethod(someargs) {
MyQueryClass query = new MyQueryClass();
Long id = query.getNextId();
// some more code
}
}
Class MyQueryClass {
....
public Long getNextId() {
//lot of DB code, execute some DB query
return id;
}
}
Now I'am writing a test for A.myMethod(someargs). I want to skip the real method query.getNextId() and instead return a stub value. Basically, I want to mock MyQueryClass.
So in my test case, I have used:
MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);
boolean b = A.getInstance().myMethod(args);
//asserts
I used #RunWith(PowerMockRunner.class) and #PrepareForTest({MyQueryClass.class}) in the beginning of my test class.
But when I debug the test, it is still calling the real method getNextId() of the MyQueryClass class.
What am I missing here? Can anyone help as I am new to Mockito and PowerMockito.
You need to put the class where the constructor is called into the #PrepareForTest annotation instead of the class which is being constructed - see Mock construction of new objects.
In your case:
✗ #PrepareForTest(MyQueryClass.class)
✓ #PrepareForTest(A.class)
More general:
✗ #PrepareForTest(NewInstanceClass.class)
✓ #PrepareForTest(ClassThatCreatesTheNewInstance.class)
As #TrueDub mentioned in his accepted reply, you need to add the class where the constructor is called to the #PrepareForTest.
However, if you do this, coverage for that class as reported by eclemma and Sonar will be zero for that class
Powermockito wiki
We are going to replace Javassist with ByteBuddy (#727) and it should
help to resolve this old issue. But right now there is NO WAY TO USE
PowerMock with JaCoCo On-the-fly instrumentation. And no workaround to
get code coverage in IDE.
So the solution here would be to refactor the actual code to use a static factory that would return an instance of that class and then statically mock it.
Perhaps you can simply use
Mockito.doReturn(value).when(xxx)
I have a folder path set in system variable through JVM arguments in Eclipse and I am trying to access it in my class as:
System.getProperty("my_files_path").
While writing junit test method for this class, I tried mocking this call as test classes do not consider JVM arguments. I have used PowerMockito to mock static System class and tried returning some path when System.getProperpty is being called.
Had #RunWith(PowerMockRunner.class) and #PrepareForTest(System.class) annotations at class level. However, System class is not getting mocked as a result I always get null result.
Any help is appreciated.
Thanks Satish. This works except with a small modification. I wrote PrepareForTest(PathFinder.class), preparing the class I am testing for test cases instead of System.class
Also, as mock works only once, I called my method right after mocking.
My code just for reference:
#RunWith(PowerMockRunner.class)
#PrepareForTest(PathInformation.class)
public class PathInformationTest {
private PathFinder pathFinder = new PathFinder();
#Test
public void testValidHTMLFilePath() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("my_files_path")).thenReturn("abc");
assertEquals("abc",pathFinder.getHtmlFolderPath());
}
}
There are certain classes PowerMock can't mock in the usual way. See here:
https://code.google.com/p/powermock/wiki/MockSystem
This, however, may still not work. In order of "good design" preference, you can fall back to these:
Refactor your code! Using a System property for passing a file path around is probably not the best way. Why not use a properties file loaded into a Properties object? Why not use getters/setters for the components that need to know this path? There are many better ways to do this.
The only reason I could think of not to do this is you're trying to wrap a test harness around code you "can't" modify.
Use #Before and #After methods to set the System property to some known value for the test(s). You could even make it part of the #Test method itself. This will be FAR easier than attempting to mock through PowerMock. Just call System.setProperty("my_files_path","fake_path");
System class is declared as final and cannot be mocked by libraries such as PowerMock. Several answers posted here are incorrect. If you are using Apache System Utils you can use getEnvironmentVariable method instead of calling System.getenv directly. SystemUtils can be mocked since it is not declared as final.
Set the system property in your test and ensure that it is restored after the test by using the rule RestoreSystemProperties of the library System Rules.
public class PathInformationTest {
private PathFinder pathFinder = new PathFinder();
#Rule
public TestRule restoreSystemProperties = new RestoreSystemProperties();
#Test
public void testValidHTMLFilePath() {
System.setProperty("my_files_path", "abc");
assertEquals("abc",pathFinder.getHtmlFolderPath());
}
}
The System.setter or getter method should be put in a user defined method and that method can be mocked to return the desired property in unit test.
public String getSysEnv(){
return System.getEnv("thisprp");
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(System.class)
public class MySuperClassTest {
#Test
public void test(){
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("java.home")).thenReturn("abc");
System.out.println(System.getProperty("java.home"));
}
}
Sailaja add System.class because as per the power mock guidelines for static,private mocking you should add the class in prepare for test.
#PrepareForTest({PathInformation.class,System.class})
Hope this helps.let me know if it doesn't work