I have a class LoggerInterceptor with an InvocationContext as parameter.
For this class I am trying to write a unit test but I am stuck on the first line:
public class LoggerInterceptor{
public method log(InvocationContext context) {
String name = invocationContext.getTarget().getClass().getName();
.....
}
My test looks like this:
#Test
public void logTest() throws Exception {
LoggerInterceptor objectToTest = new LoggerInterceptor();
InvocationContext context = Mockito.mock(InvocationContext.class);
Object target = Mockito.mock(Object.class);
Mockito.when(context.getTarget()).thenReturn(target);
MockGateway.MOCK_GET_CLASS_METHOD = true;
Mockito.doReturn(objectToTest.getClass()).when(target).getClass();
MockGateway.MOCK_GET_CLASS_METHOD = false;
objectToTest.log(context);
}
I am getting a UnfinishedStubbingException when I call the method log(context).
If I try with:
Mockito.when(target.getClass()).thenReturn(objectToTest.getClass());
I get this exception:
The method thenReturn(Class<capture#3-of ? extends Object>) in the type OngoingStubbing<Class<capture#3-of ? extends Object>> is not applicable for the arguments (Class<capture#4-of ? extends LoggerInterceptor>)
Is there any way I can pass this first line? The String that I get back is not important.
Object.getClass() is final. Final methods can't be mocked or stubbed with Mockito, because the compiler sees "final", skips the virtual method dispatch, and consequently Mockito can neither intercept calls to the method nor identify the method in doReturn, when, or verify. When you interact with Mockito later, it detects that you started stubbing but cannot detect that you finished, so it throws an UnfinishedStubbingException.
If you want to have target adjust the type or types it appears as, you'll need to change the class object passed into Mockito.mock, or add withSettings().extraInterfaces(...).
Related
Basically, I'm trying to set the result of a final method. The method is simple, like this:
#NotNull
public final Server getServer() {
return this.server;
}
I mock it like this:
EasyMock.expect(object.getServer()).andReturn(server);
Where server is a POJO. This throws this:
java.lang.IllegalStateException: incompatible return value type
at org.easymock.internal.MocksControl.andReturn(MocksControl.java:281)
For that line.
I tried not using a POJO for server, and mocking it instead.
#Mock
private Server server = mock(Server.class);
Yet still the same error. I'm absolutely positive that they are the exact same type. Why is this happening?
Now, for some reason I get a different error:
java.lang.IllegalStateException: no last call on a mock available
Same code, all I have is this:
#Test
public void test() {
EasyMock.expect(object.getServer()).andReturn(server);
replayAll();
TestedObject.useObject(object);
}
The reason you get an error when mocking a final method is that it is not supported by EasyMock. https://easymock.org/user-guide.html#mocking-limitations
Final methods cannot be mocked. If called, their normal code will be executed.
You can use PowerMock to mock final and static methods.
Want to ask you a question.
How should I properly return some data from method called from testable class ?
For example I have next structure:
Class SomeClass {
public void method1(){
//some logic here
List<Object> howToReturnHereValues = gatData();
//some logic here
}
public List<Object> getData(){
return List<Object>;
}
}
Right now I want to test method1(), but I don't know how to mock call getData() which returns List<Object>.
Any advice please ?
You can do this using a spy, like explained here: https://static.javadoc.io/org.mockito/mockito-core/2.7.17/org/mockito/Mockito.html#13
Example:
#Test
public void testMethod1() throws Exception {
SomeClass someClass = new SomeClass();
SomeClass spy = Mockito.spy(someClass);
Mockito.when(spy.getData()).thenReturn(Arrays.asList("blaat", "blabla"));
spy.method1();
}
This will return a List of "blaat" and "blabla" which can be used by the logic in your method1.
Right now I want to test method1(), but I don't know how to mock call
getData() which returns List.
It is rather a bad idea to mock a public method of a class that is under test.
A unit test should test a behavior and mock dependencies. Here, you unit test only a part of the behavior as you mock the behavior of the tested class.
If the class is ours you could :
either test this method without mocking the getData() called public method.
or move the getData() public method in another class and then mock this new dependency if you don't want to repeat the test of the getData() method in each test method calling it.
If the class is not modifiable and the mocked called is really required, you could use the spy() method of the Mockito framework on the object under test to simulate a mocked behavior for a specific method.
I m trying to mock an interface.
public interface FlowCopyParamsBusinessManager {
List<FlowCopyParams> findByAppli(String application, String sourcePattern)
throws FlowCopyParamsBusinessException;
}
In my code, when i call this method findByAppli, i would like to return a list of FlowCopyParams.
List<FlowCopyParams> lstFlowCopyParams = flowCopyParamsBusinessManager.findByAppli(
"TOTO","TATA);
Here my try in the class test:
#BeforeClass
public static void mockBeanIn() throws Exception {
List<FlowCopyParams> flowCopyParamsList = new ArrayList<>();
PowerMockito.spy(FlowCopyParamsBusinessManager.class);
PowerMockito.when(FlowCopyParamsBusinessManager.class, "findByAppli", Mockito.anyString(), Mockito.anyString()).thenReturn(flowCopyParamsList);
}
I have this error :
java.lang.IllegalArgumentException: object is not an instance of declaring class
I don't know why because the method findByAppli must have two string parameters, and i put Mockito.anyString() and i still have IllegalArgumentException.
Any clue ?
Thxs.
You don't need to use PowerMockito, and as its an Interface, theres no need to spy() as you are not relying on any non mocked logic.
It can be done like this, in your test class define a class variable.
private FlowCopyParamsBusinessManager flowCopyParamsBusinessManagerMock;
In an #Before annotated method:
flowCopyParamsBusinessManagerMock = Mockito.mock(FlowCopyParamsBusinessManager.class);
List<FlowCopyParams> flowCopyParamsList = new ArrayList<>();
when(flowCopyParamsBusinessManagerMock
.findByAppli(Mockito.anyString(), Mockito.anyString()).thenReturn(flowCopyParamsList);
Then refer to flowCopyParamsBusinessManagerMock in your tests.
My test did not work because I was trying to spy the class and not on the instance of FlowCopyParamsBusinessManager.class .
First , we have to create the mock :
FlowCopyParamsBusinessManager mockFlowCopyParamsBusinessManager = PowerMockito.mock(FlowCopyParamsBusinessManager.class);
Then , spy the instance :
PowerMockito.spy(mockFlowCopyParamsBusinessManager);
PowerMockito.when(mockFlowCopyParamsBusinessManager, "findByAppli", Mockito.anyString(), Mockito.anyString()).thenReturn(flowCopyParamsList);
It works as well !
I did this put this #RunWith(PowerMockRunner.class) at the top of the class. then mock Object with PowerMockito.mock(MyMock.class); This way use can mock a interface or final class.
I have an internal StreamGobbler class that has 7 methods in it.
I'm looking for a quick way to mock all the methods by default, but override one method named getOutput() (e.g. Partial Mocking).
(full code not shown for clarity)
public class StreamGobbler extends Thread
{
public String getOutput()
public void run()
}
What I would like is to use something like the #Mocked annotation in combination with MockUp to partially mock the getOutput method, but retain all the "default" mocking code on all the other methods. In the docs on partial mocking, it makes the point that if you use MockUp, all non #Mock methods retain their normal functionality. Sometimes that is great, but that isn't what I want in this case.
This is similar to the question JMockit: #Mocke and MockUp combination in the same test, but I can't get away with just looking at method counts.
If I have a test setup like this:
#Test
public void execute(#Mocked StreamGobbler sg)
{
new MockUp<StreamGobbler>()
{
String type = null;
#Mock
void $init(String type)
{
this.type = type;
}
#Mock
String getOutput()
{
if ("OUTPUT".equals(type))
{
return "test output";
}
else
{
return "";
}
}
}
}
I get this error java.lang.IllegalArgumentException: Class already mocked
If I try to add the #Override annotation in the MockUp, it doesn't help (and Eclipse complains about it)
What is the best way to handle this? Use a static class outside this test method?
Using JMockit 1.17, and TestNG
In summary, how do I get every method in StreamGobbler mocked (as with #Mocked), but partially override one method (without manually doing it myself inside the MockUp?)
Full example code which meets the given constraints:
public static class StreamGobbler extends Thread {
public StreamGobbler(String type) {}
public String getOutput() { return null; }
#Override public void run() {}
}
public static class TestedClass {
public String doSomething() throws InterruptedException {
StreamGobbler sg1 = new StreamGobbler("OUTPUT");
sg1.start();
StreamGobbler sg2 = new StreamGobbler("ERROR");
sg2.start();
sg1.join(5000);
sg2.join(5000);
String output1 = sg1.getOutput();
String output2 = sg2.getOutput();
return output1 + '|' + output2;
}
}
#Test
public void useStreamGobbler(#Mocked StreamGobbler sg) throws Exception {
new Expectations() {{
new StreamGobbler("OUTPUT").getOutput(); result = "test output";
new StreamGobbler("ERROR").getOutput(); result = "";
}};
String output = new TestedClass().doSomething();
assertEquals("test output|", output);
}
Firstly, since you are creating an anonymous subclass of the MockUp class, using the #Override annotation would certainly be inappropriate. Those methods that you are providing do not belong to the MockUp class, but the generic you are providing.
Later on during runtime, (through some impressive process (based on what I read here, I'm assuming AOP)) the instance you create in this class will then use your provided method signatures instead of its own.
After reading the API on the Mock class more thoroughly as well as getting some information from JMockit's Getting Started page, I think you're issue lies in a different area entirely. If you have other test methods, they will be interfering with this method.
The error you are getting is saying: "There is already an instance of MockUp declared for the type StreamGobbler, and by calling the Mocked annotation in this test method's parameters and attempting to declare another instance of MockUp with the same generic, you are violating a JMockit stipulation."
I would check to see if you are creating an actual MockUp of StreamGobbler outside of the test method and if so (1) if you want to use it, don't redeclare another instance of MockUp in the method but continue to use the Mocked annotation or (2) if you do not want to use it and you want to re-declare a new instance of MockUp wrapping StreamGobbler, do not use the Mocked annotation in the test method's parameters but keep the MockUp instantiation.
I want to throw a ContentIOException from a method whose signature look like this.
public void putContent(InputStream is) throws ContentIOException.
When I try to throw ContentIOException from Mockito like such:
when(StubbedObject.putContent(contentStream)).thenThrow(ContentIOException.class);
I get the following compilation error:
The method when(T) in the type Mockito is not applicable for the arguments (void).
What am I doing wrong?
Take a look at this reference in the official API. You want to reverse the way your call is made and adjust the argument too, since this is a void method that you expect to throw an exception.
doThrow(new ContentIOException()).when(StubbedObject).putContent(contentStream);
You can use following code
when(testRepositoryMock.findOne(123)).thenThrow(new NullPointerException());
Then after you can check your logic
String erroResponse= service.testMethodForResponse(accountNum);
JSONObject jsonObj = new JSONObject(erroResponse);
String _acNo = jsonObj.getString("accountNum");
assertEquals(accountNum, _acNo);
}
If you are using Spring boot then add top of class
#SpringBootTest
#RunWith(MockitoJUnitRunner.class)
Inside of class you need to inject object
#InjectMocks //actual object you want to get test coverage
private TestService testService;
#Mock //Mock object which call by actual object for mocking
private testRepository testRepositoryMock;
Reference link :http://www.baeldung.com/mockito-behavior