How do I set a property on a mocked object using Mockito? - java

I have a scenario where I have to set a property of a mocked object as follows:
SlingHttpRequest slingHttpRequest= mock(SlingHttpRequest);
slingHttpRequest.setAttribute("search", someObject);
When I try to print this attribute I get null. How do I set this property?

You don't normally set properties on your mocked objects; instead, you do some specific thing when it's invoked.
when(slingHttpRequest.getAttribute("search")).thenReturn(someObject);

I'm afraid you're misusing your mock SlingHttpRequest.
Mockito requires you to wire up your mock's properties before you use them in your test scenarios, i.e.:
Mockito.when(slingHttpRequest.getAttribute("search")).thenReturn(new Attribute());
You cannot call the setAttribute(final Attribute a) method during the test like so:
slingHttpRequest.setAttribute(someObject);
If you do this, when the test runs, getAttribute() will return null.
Incidently, if the code you are unit testing is going to call a setter on your mock in this way, do not use a mock. Use a stub.

Mock object is not where you store data, it's for you to teach the behavior when its methods are invoked.
try this: https://www.google.com/search?q=mockito+example&oq=mockito+example&aqs=chrome..69i57j0l5.6790j0j7&sourceid=chrome&espv=210&es_sm=93&ie=UTF-8

I'm probable 7 years late for the party, but I still would like to contribute.
You CAN set class property using the Whitebox from powermock:
Whitebox.setInternalState(mockedClass, "internalField", "Value to be returned")

Related

How to pass param to mocked class method?

I am using mockito to test mu jdk11-springboot application.
My application has class 'ClientRepository' and that has a method called 'findById' which takes a param of type UUID.
SO the method looks like :
public String findById(UUID id)
Now I mocked the class to test as :
#MockBean
private ClientRepository clientRepo;
Now I am trying to figure out how to pass the UUID param here:
Mockito.when(clientRepo.findById(UUID id))
.thenReturn(dslContext.selectFrom(CLIENT).where(CLIENT.ID.eq(UUID.fromString("3e064b19-ef76-4aea-bf82-e9d8d01daf1c"))).fetch());
Can anyone help?
You can use the following construction:
UUID expected = ...;
Mockito.when(clientRepo.findById(Mockito.eq(expected))).thenReturn(...);
This can be a good solution if the expected UUID is not the same instance that you configure in the test.
Another point to consider:
You seem to use JOOQ but have a mock bean for repository, which means that you probably test some kind of service (business logic layer).
In this case maybe you don’t need to work with database at all, just create a string and return in thenReturn part of the mocking configuration
Mockito.when(clientRepo.findById(Mockito.any(UUID.class))
.thenReturn(dslContext.selectFrom(CLIENT).where(CLIENT.ID.eq(UUID.fromString("3e064b19-ef76-4aea-bf82-e9d8d01daf1c"))).fetch());
Use Mockito.eq("your-uuid-goes-here") instead if your mock should only react to specific values.
Passing the value directly for which the mock is expected to return should also work.
Mockito.when(clientRepo.findById(<expected UUID>)
.thenReturn(dslContext.selectFrom(CLIENT).where(CLIENT.ID.eq(UUID.fromString("3e064b19-ef76-4aea-bf82-e9d8d01daf1c"))).fetch());

How do I test a void method using JUnit and Mockito?

My void method changes boolean variable value in the class. How do DI check that?
I have:
mocked class object
called the method with proper parameters
checked the instance variable
But that doesn't change the value of instance variable. How do I do this?
ReferenceLettersBean rf = Mockito.mock(ReferenceLettersBean.class);
rf.setBoolcheck(false);
Mockito.doNothing().when(rf).checkForDuplicates(anyString(), anyString(), anyString());
rf.checkForDuplicates("abcd#emal.com","abd#gmail.com","abcd#gmail.com");
assertEquals(true,rf.getBoolcheck());
DON'T mock the class you are trying to test.
DO mock the classes that interact with the class you are trying to test.
If you want to test that a field in a a class changes from false to true, what you really want to do is something like (I don't have your actual constructor, I'm just guessing):
SomeDependency dependency = mock(SomeDependency.class);
// Make a REAL ReferenceLettersBean
ReferenceLettersBean bean = new ReferenceLettersBean(dependency);
// now make your test
rf.checkForDuplicates("abcd#emal.com","abd#gmail.com","abcd#gmail.com");
assertEquals(true,rf.getBoolcheck());
This boolean value seems to be an internal state. This is not something you can directly test with unit tests unless you make it public or it is detectable by influencing the behavior of another method.

How to properly mock varargs with Mockito

I have this method, "instance" is #Mock
instance.lookup(
SomeClass.class.getField("field").getAnnotation(MyAnnotation.class),
Annotation... annotations
)
Signature of that method is exactly this:
Object lookup(MyAnnotation resource, Annotation... annotations);
Now, that Annotation... value is put there on that mock in runtime in the code I test.
I am trying to Mock it so when I do
Mockito.when(instance.lookup....).thenReturn(something);
but lookup method always returns null value and exception it thrown (it basically do not return "something" but null)
I was thinking that I have to mock these varargs as well so I modified it to this
Mockito.when(instance.lookup(_instance line_, Mockito.any(Annotation[].class)))
but it fails telling me that I am using it "raw".
When I use anyVarargs() like this
Mockito.when(instance.lookup(_that line_, Mockito.anyVararg()))
Mockito.anyVararg() returns Object but I need Annotation[]
Any hint here?
Thanks a lot!

Powermock not returning correct object static method

I am using PowerMock to try and mock a final class with static methods, but whenever my code calls MyClass.getInstance() it returns null
In my tests I have annotated the test class
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
In my method to make the mock I do the following
suppressConstructor(MyClass.class);
PowerMock.mockStatic(MyClass.class);
mockClass = PowerMock.createMock(MyClass.class);
expect(MyClass.getInstance()).andReturn(mockClass);
Should PowerMock.createMock create an EasyMock class?
When I call this in my code (MyClass.getInstance()), it always returns null but if I step through the test class the variable mockClass gets instantiated.
It seems like you using the EasyMock way of mocking. Have you replayed the MyClass before calling the getInstance() method, e.g.
PowerMock.replay(MyClass.class);
?
From the PowerMock MockStatic documentation:
Use PowerMock.mockStatic(ClassThatContainsStaticMethod.class) to mock all methods of this class.
Use PowerMock.replay(ClassThatContainsStaticMethod.class) to change the class to replay mode.
Use PowerMock.verify(ClassThatContainsStaticMethod.class) to change the class to verify mode.

Mockito Exception - when() requires an argument which has to be a method call on a mock

I have a very simple test case that is using Mockito and Spring Test framework. When I do
when(pcUserService.read("1")).thenReturn(pcUser);
I get this exception.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
at com.project.cleaner.controller.test.PcUserControllerTest.shouldGetPcUser(PcUserControllerTest.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
I have tried with different methods but keep on getting this error message. I am using Spring 3.1.0.RELEASE with Mockito. Please share and guide me in the right direction.
You need to create a MOCK of pcUserService first, and then use that mock.
PcUserService mock = org.mockito.Mockito.mock(PcUserService.class);
when(mock.read("1")).thenReturn(pcUser);
In case others hit this issue....
It could also be the case that the method you are trying to mock out,pcUserService.read, is declared as a final method. From what I've noticed this appears to cause issues with Mockito.
If you use Kotlin, you should know that methods are final by default. So write open fun instead of fun. Thanks to #djkelly99 for a tip.
Another solution to this issue might be that in case of a test class that is using PowerMockRunner, you might have to add the class that you are mocking to the list, in #PrepareForTest annotation.
For instance -
#PrepareForTest({ PcUserService.class })
In my case it was solved by injecting #MockBean.
For ex.
#MockBean
StateRepository mockStateRepository;
There's another possible reason for such error - sometimes IDE prefers to statically import Mockito.when() from another package:
import static io.codearte.catchexception.shade.mockito.Mockito.when;
vs
import static org.mockito.Mockito.when; //should normally use this one
The thing is 'when' from io.codearte package is compliant with org.mockito.Mockito.any() on compilation level, but fails during runtime with that exact same error message.
I had the same issue, the method that I was trying to mock it was a final method. I removed the modifier and it worked fine.
For the help of others who stuck with the same problem;
The method you are trying to mock , pcUserService.read, is declared as a final method. Static methods appears to cause issues with Mockito.
If you get this exception when using MockedStatic or Mockito.mockStatic, it can also mean that you are mixing matchers and literals in the call to the static method.
Try changing any mixes like YourClass.staticMethod(any(), "literal") to YourClass.staticMethod(any(), eq("literal"))
Basically You need to use the PowerMockito.mockStatic to enable static mocking for all static methods of a class. This means make it possible to stub them using the when-thenReturn syntax.
For example:
PowerMockito.mockStatic(TestClass.class);
when(TestClass.getString()).thenReturn("HelloWorld!");
Note: you have to add #PrepareForTest({ TestClass.class }) to your unit test class.
If you use KOIN, include in the gradle's dependencies:
dependencies {
...
testImplementation "org.koin:koin-test:2.0.0"
}
I faced similar issue when mocking static method of anotherClass called inside testing a method of someClass. In that case, we need to add #PrepareForTest({anotherClass.class, someClass.class}) both the class having the static method and caller class.
When I got this exception, I was using #InjectMocks on the class that I needed to have the #Mock objects injected into (via constructor injection).
AFter much searching, I finally stumbled across this article:
https://mkyong.com/spring-boot/mockito-when-requires-an-argument-which-has-to-be-a-method-call-on-a-mock/
The key part to take away from it is (from the article):
When Mockito see this #InjectMocks, it doesn’t mock it, it just
creates a normal instance, so the when() will be failed.
So this make this exception message I was getting
when() requires an argument which has to be 'a method call on a mock'.
make sense now; you aren't using when on an actual mock but an actual instance.
The link also provides the solution to the problem:
To solve it, annotate #Spy to mock it partially.
On top of #InjectMocks, put #Spy.
As a side note, if you try to make it a Mock by putting #Mock on top of #InjectMocks, you will get exception:
org.mockito.exceptions.base.MockitoException: This combination of
annotations is not permitted on a single field: #Mock and #InjectMocks
Using #Spy on top of #InjectMocks solved the problem for me.
I faced same issue and it was because the mocked object is defined as #Beanand the overriden #Bean in the test was not working because of a missing spring property value
#Bean
#Primary
public JwtTokenUtil jwtTokenUtil() {
return Mockito.mock(JwtTokenUtil.class);
}
#Autowired
private JwtTokenUtil jwtTokenUtil;
when(jwtTokenUtil.validateToken(jwtToken)).thenReturn(true);
Fix
spring.main.allow-bean-definition-overriding=true in application-test.properties
if anything above answers your case, then check that you did missed the #Test annotation for your test method.
#Test
public void my_test_method(){
}
just quoting, as this was my case. just missed the annotation.

Categories

Resources