I'm trying to partially mock a service using Mockito's Spy, overriding a method to make it return consistent data for testing, but said spy throws an UnfinishedStubbingException for no apparent reason.
This is my test class:
#SpringBootTest
#RunWith(SpringRunner.class)
public class ApplicationIT {
private CompletableFuture<JobList> jobList;
#SpyBean
private Service serviceSpy;
#Before
public void setUp() {
initMocks(this);
jobList = new CompletableFuture<>();
jobList.complete(jobList.newBuilder()
.addAllJobs(jobTestData.getTestJob().getJobs()).build());
Mockito.doReturn(jobList).when(serviceSpy).fetchJob();
Mockito.doNothing().when(serviceSpy).reportSuccess(Mockito.any());
}
#Test
public void fetchJobCallTest() {
Mockito.verify(serviceSpy, timeout(60000).atLeastOnce()).fetchJob();
}
#Test
public void reportSuccessCallTest() {
Mockito.verify(serviceSpy, timeout(60000).atLeastOnce()).reportSuccess(Mockito.any());
}
}
Both tests fail with a org.mockito.exceptions.misusing.UnfinishedStubbingException pointing to Mockito.doReturn(jobList).when(serviceSpy).fetchJob(); at Mockito.doNothing().when(serviceSpy).reportSuccess(Mockito.any());
UnfinishedStubbingException means you are not mocking properly
this is not the right way of mocking a method... Mockito.doReturn(jobList).when(serviceSpy).fetchJob();
You can try below...
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Related
I would like know, how can I make a JUnit ignore #Before only in oone method Test.
I found how to ignore in a Class, but I need only in one Test.
You may use #Rule for that. Here is an example:
public class ExampleUnitTest {
#Rule
public TestName testName = new TestName();
#Before
public void init() {
if (testName.getMethodName().equals("someTest")) {
// your logic for the `someTest` method
} else {
// logic for the rest of the tests
}
}
#Test
public void someTest() {
//
}
#Test
public void anotherTest() {
//
}
#Test
public void yetAnotherTest() {
//
}
}
However, how #mslowiak pointed already, this is not a good idea. The JUnit core concept is test isolation. So, if you need different init steps for the different tests you might be doing something wrong.
The reason for #Before annotation is to have consistent behavior in every test.
In your case extracting before logic to a method and call it with each required test would be a better idea.
I am trying to mock an Impl that contains 2 static members A, B, and a static method Utils.SomeMethod. I tried to mix PowerMock and Mockito initially but was not sure if this was causing the problem so I changed all refs to PowerMockito. I get unit test failures that mocks are not getting invoked. if I remove statics and just use Mockito then all tests succeed.
Here is a brief outline of the problem.
class Impl {
static A a;
static B b;
private static final String s = Utils.SomeMethod();
void mainMethod() {
a.aMethod("foo");
b.bMethod("bar");
}
}
So in my unit test I have
#PowerMockIgnore({"javax.net.ssl.*" , "javax.crypto.*"})
#RunWith(PowerMockRunner.class)
#PrepareForTest({Utils.class})
public class ImplTest {
A a;
B b;
#Captor
ArgumentCaptor<String> argumentCaptor;
#BeforeClass
static public void setUp() {
PowerMockito.mockStatic(Utils.class);
PowerMockito.when(Utils.SomeMethod()).thenReturn("test"); // works
}
#Before
public void before() {
a = PowerMockito.mock(A.class);
b = PowerMockito.mock(B.class);
impl = PowerMockito.mock(Impl.class);
impl.setA(a); // I tried #Mock and #InjectMocks but seemed to not work on statics, works with non static members
impl.setB(b);
}
#Test
public void test() {
PowerMockito.when(a
.aMethod(any(String.class))
.thenReturn("hmm");
PowerMockito.when(b.bMethod(any(String.class))
.thenReturn("yo");
impl.mainMethod();
verify(a, times(1)).aMethod(argumentCaptor.capture());
// fails that 0 times mock was invoked
}
}
As I can see it you are mocking Impl but you should instantiate it if you want mainMethod invoke your static methods.
Also, are you initializing argumentCaptor somewhere in your code?
I'd like to suggest using Mockito for most testing mocks, and using PowerMockito only when dealing with some static methods. With slight changes, your test code worked ok:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Utils.class })
public class ImplTest {
#Mock
A a;
#Mock
B b;
#Captor
ArgumentCaptor<String> argumentCaptor;
#BeforeClass
static public void setUp() {
PowerMockito.mockStatic(Utils.class);
Mockito.when(Utils.SomeMethod()).thenReturn("test"); // works
}
Impl impl;
#Before
public void before() {
Impl.setA(a);
Impl.setB(b);
impl = new Impl();
}
#Test
public void test() {
Mockito
.when(a.aMethod(Matchers.any(String.class)))
.thenReturn("hmmm");
Mockito
.when(b.bMethod(Matchers.any(String.class)))
.thenReturn("yo");
impl.mainMethod();
Mockito.verify(a, Mockito.times(1)).aMethod(argumentCaptor.capture());
Assert.assertEquals("foo", argumentCaptor.getValue());
Mockito.verify(b, Mockito.times(1)).bMethod(argumentCaptor.capture());
Assert.assertEquals("bar", argumentCaptor.getValue());
}
}
Please notice that if A and B are defined as static, they should be injected into the class, not into individual instance(s).
#InjectMocks will not work in this context, since it requires a different Runner. Please have a look at this other article Difference between #Mock and #InjectMocks
I would like to perform a junit test using Mockito on the toEntity function.
#Component
public class MyEntityTransform {
public Function<MyDTO , MyEntity> toEntity = new Function<MyDTO , MyEntity >() {
#Override
public MyEntity apply(MyDTO record) {
return new MyEntity();
}
};
}
Unfortunately the toEntity is NULL when I mock the class and I don't know how I can test it correctly.
#RunWith(MockitoJUnitRunner.class)
public class MyTest {
#InjectMocks
private MyService _classUnderTest;
#Mock
private MyEntityTransform myEntityTransform
#Before
public void setUp() {
Mockito.when(this.myEntityTransform.toEntity.apply(Mockito.anyObject())).thenReturn(...);
}
}
When I RUN the JUNIT test, Mockito give me the error :
java.lang.NullPointerException
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at com.example.MyTest.setUp(MyTest.java:38)
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
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.
Do you have suggestions?
You're using public fields, which is not a good idea. But anyway, what you want to mock is the function, not the instance of MyEntityTransform. So you would need something like
#InjectMocks
private MyService _classUnderTest;
#Mock // or #Spy
private MyEntityTransform myEntityTransform;
#Before
public void prepare() {
myEntityTransform.toEntity = mock(Function.class);
}
But quite frankly, I wouldn't use a public field of type Function. Instead, I would use a public method:
public class MyEntityTransform {
public MyEntity toEntity(MyDTO record) {
return new MyEntity();
}
}
Then you can mock MyEntityTransform and make its toEntity method return what you want. And if you need to pass a Function doing what the method does, use a method reference:
collection.stream().map(myEntityTranform::toEntity)
This fails with InitializationError. Other tests in the same package run so I have done something silly in my code. Stacktrace reads "No tests found matching [[Exactmatch]]".
public class TestClassToTest {
#Mock
File mockOfAFile;
#Test
public void testAMethod(File mockOfAFile) {
MockitoAnnotations.initMocks(this);
given(fileMock.getName()).willReturn("test1");
assertEquals("test1",ClassBeingTested.methodBeingTested(mockOfAFile));
}
}
Have tried everything but am very new to Mockito. What silly thing am I doing here ?
Thanks
I found two things to fix:
The #Test method should have no parameters
You need another File instance, called fileMock.
So here is the updated code:
public class TestClassToTest {
#Mock
File mockOfAFile;
#Mock
File fileMock; // the new mock
#Test
public void testAMethod() { // no parameters
MockitoAnnotations.initMocks(this);
given(fileMock.getName()).willReturn("test1"); // here is the new mock used
assertEquals("test1",ClassBeingTested.methodBeingTested(mockOfAFile));
}
}
I have a little problem here, and I don't know how to solve it.
I have a class which have to make tests for some JSF beans.
In order to achieve that, I used PowerMock with Mockito for mocking the FacesContext, RequestContext and another static methods which are used inside the JSF beans.
#PrepareForTest(ClassWithStaticMethods.class)
#RunWith(PowerMockRunner.class)
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MyTestingClass extends SomeTestBaseClass{
#BeforeClass
public static void init() throws Exception{
//mocking the FacesContext and others
}
#Test
public void test0001Create(){}
#Test
public void test0002Edit(){}
#Test
public void test0003Delete(){}
}
The SomeTestBaseClass, nothing complicated.
public abstract class SomeTestBaseClass {
#BeforeClass
public static void setUpBeforeClass() throws Exception {
//...
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
//...
}
}
The problem is that the order of tests is ignored (even with the FixMethodOrder annotation). If I remove PowerMockRunner (and the RunWith annotation), the order is kept but the mocking for static (and void) methods doesn't work.
But leaving the class with PowerMockRunner, the annotation #FixMethodOrder is ignored, totally.
I even tried with MockitoJUnitRunner, and here the order of tests is kept, but the mocking for static (and void) methods isn't done.
Does anyone have any idea why it is happening?
Thanks
I had the same problem getting them to run in the right order.
I solved it by using the #PowerMockRunnerDelegate annotation.
In my test class annotations:
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
#RunWith(PowerMockRunner.class)
I added #PowerMockRunnerDelegate(JUnit4.class):
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(JUnit4.class)
They now run in the expected order.
I believe this works because then it's not PowerMock that's running the tests, but JUnit 4 itself.
Like a workaround: Create a new method (let's say 'testAll'), put #Test annotation just for this (remove the #Test annotation from the rest of the methods), and then, call your testing methods inside of the annoted method.
Dirty, but it works.
#PrepareForTest(ClassWithStaticMethods.class)
#RunWith(PowerMockRunner.class)
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MyTestingClass extends SomeTestBaseClass{
#BeforeClass
public static void init() throws Exception{
//mocking the FacesContext and others
}
#Test
public void testAll(){
this.test0001Create();
this.test0002Edit();
this.test0003Delete();
}
public void test0001Create(){}
public void test0002Edit(){}
public void test0003Delete(){}
}
Please try to change sequence:
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassWithStaticMethods.class)
I don't know why it doesn't work with the PowerMockRunner annotation but instead you could use a PowerMockRule
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MyTestingClass extends SomeTestBaseClass {
#Rule
public PowerMockRule rule = new PowerMockRule();
#BeforeClass
public static void init() throws Exception {
// mocking the FacesContext and others
}
#Test
public void test0001Create() {
}
#Test
public void test0002Create() {
}
#Test
public void test0003Create() {
}
}