I have a method in a class lets say doStuff which calls another method of another class execute:
#Component
class A {
#Autowired
B b;
int doStuff(){
return b.execute(1);
}
}
#Component
class B {
int execute(int i){
return i;
}
}
Now when I'm trying to mock the method execute, it is throwing nullPointer
#ExtendWith(MockitoExtension.class)
public class ATest{
#InjectMocks
A a;
#Mock
B b;
#Test
doStuffTest(){
when(b.execute(anyInt()).thenReturn(1);
assertEquals(1,a.doStuff());
}
}
It is throwing NullPointer Exception on line when(b.execute(anyInt()).thenReturn(1);
#Autowired annotation is part of Spring, while #Mock is part of Mockito. #Autowired will not be triggered using the Mockito test. Mocked class has to be a constructor where object can be injected by #InjectMock.
If you want to use #Autowired you need a Spring context like #SpringBootTest or others that scan and configuration your project. So, if you would like to mock this bean, you will have to #MockBean annotation.
Issue resolved with #RunWith(MockitoJUnitRunner.class) annotation, without that it's failing
Related
I have a singleton class (so private constructor) which needs to use a Spring Data repository during initialization. I have one injected as a constructor argument. Roughly:
#Controller
public class MyClass {
#Autowired
private MyClass(MyRepository repo) {
repo.findAll();
}
}
I want to unit test my class, so I need to have a mock repository initialized with mock values and then passed into my class before my class is initialized. How do I write my Mockito mocks in my JUnit test to make this possible?
You don't need Spring; this is an advantage of constructor injection. Just use MyRepository mockRepo = mock(MyRepository.class) and new MyClass(mockRepo).
(Your constructor should be public, by the way. You seem to be making the common mistake of confusing different senses of "singleton"; in the case of DI it simply means that the container only makes a single instance and shares it. Finally, if you only have one constructor you don't need #Autowired.)
Unit test should be independent. It means, we are not using real data from database even call any service from our test file.
Assuming you are using JUni5 and have findAllStudents() in your controller. So your test file approximately like this
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class MyClassTest {
#Mock
private MyRepository repo;
#InjectMocks
private MyClass controller;
#BeforeAll
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testDataIsExist() {
List<String> expectednames = new ArrayList();
expectedNames.add("Foo");
expectedNames.add("Bar");
Mockito.when(myRepo.findAll()).thenReturn(expectedNames);
List<String> result = controller.findAllStudents();
Assertions.assertNotNull(result);
Assertions.assertEquals(expectednames, result);
}
}
So we are mock all the services we use in controller, then inject to controller itself. Then inside the test method we mock repo.findAll() to return expectedNames so if the controller find that function it will return what mock says to return.
After we call the function, we have to make it sure that the result is according to what we expected.
There is little value in a "unit test" for a #Controller implementation. If you use #WebMvcTest, then you can use #MockBean:
#WebMvcTest
class MyControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private MyRepository repository;
#Test
void testSomething() {
mockMvc.perform( ... );
}
}
In my SpringBootApplication, I have a bean which injects another optional bean (like shown below)
#Service
public class A {
//B is another #Component from one of the dependencies
private Optional<B> b;
...
...
}
I am writing an integration test for class A where I need to #MockBean Optional<B> b. However since Optional is a final class, spring mockito raises following error
Cannot mock/spy class java.util.Optional
- final class
Is there a way around this? Any help is much appreciated.
You can use Optional.of(b).
If you use mockito with annotations, then you can't use #InjectMocks because your optional will not be known for mockito. You have to create your service A yourself. Something like this:
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#Mock
private B b;
private A a;
#Before
public void setup() {
a = new A(Optional.of(b));
}
}
You should actually mock the actual bean using #MockBean or #MockBeans or TestConfig class and Autowire the Optional with mocked bean
#Autowired
private Optional<B> OptionalB;
#MockBean
private B b;
Although Lino's above answer works perfectly, I chose not to modify the production code to make the test work. I've instead modified my code like below:
#Service
public class A {
#Autowired(required = false)
private B b;
...
...
}
When I'm making a Test, I can't get injected a property of one of the injected beans (with #Spy). I am using Mockito to test.
I tried using #Mock, #Spy, #SpyBean and #InjectMocks in this Bean on my test but I can't get it injected.
#RunWith(MockitoJUnitRunner.class)
public class MyTest{
#InjectMocks private MyService = new myService();
#Spy private MyFirtsDepen firstDepen;
#Autowired #Spy private ChildDepen childDepen;
... More mocks and tests
}
#Service
public class MyService {
#Autowired private MyFirstDepen firstDepen;
....
}
#Mapper
public class MyFirstDepen {
#Autowired private ChildDepen childDepen;
....
}
#Component
public class ChildDepen {
...
}
When my test use firstDepen is working great, but when firstDepen uses childDepend always get Nullpointer. How can I inject this property in my test?
Since your MyFirtsDepen is a mock, there is no way to inject anything to it. Configure mock to return another mock.
when(firstDepen.getChildDepen()).doReturn(childDepen);
I have a class I want to test that has several external dependencies, and a couple internal methods. I would like to write a test for MethodA, but not have Method A's internal call to MethodB to actually exercise MethodB. I'd like to mock/stub MethodB and return something specific instead. Usually I'd use when/thenReturn but it doesn't behave like I expect - it actually jumps into Method B while creating the mock itself.
MyService.java
#Service
public class MyService {
#Autowired
private ServiceA serviceA;
#Autowired
private ServiceB serviceB;
public SomeObject methodA() {
// some logic using serviceA.method and serviceB.method that creates "output"
SomeObject someObject = methodB(output);
return someObject;
}
public SomeObject methodB(SomeObject someObject) {
// deep mysteries done here to someObject
return someObject
}
}
MyServiceTest.java
public class MyServiceTest {
#Mock
private ServiceA serviceA;
#Mock
private ServiceB serviceB;
#InjectMocks
private MyService myService;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void methodATest() {
when(serviceA.method()).thenReturn(stuff);
when(serviceB.method()).thenReturn(otherStuff);
// here is what I would like to do
when(myService.methodB()).thenReturn(mockedSomeObject); //<- doesn't work
assertThat(myService.methodA().getSomeObjectProperty())
.isEqualTo("property");
}
}
I've looked at solutions that manually mock the MyService class with Mockito.mock(MyService.class), but (as the above example is obviously contrived) my actual class has quite a few external dependencies and I'd prefer a solution that still allows me to mock the service using #Mock for the #Autowired dependencies and #InitMocks for the class under test, unless it's simply not possible.
I've tried:
Mockito.doReturn(mockedSomeObject).when(myService.methodB(any(SomeObject.class));
but that also steps into MethodB when creating the mock for that method, which shouldn't be happening.
Thanks in advance for the help!
Try Adding #Spy to your InjectMocks and use the object to "expect" them in a slightly different syntax.
import org.mockito.Spy;
#InjectMocks
#Spy
private MyService myService;
And now mock the service call
Mockito.doReturn(mockedSomeObject).when(myService).methodB();
Also change the other mock call to this
Mockito.doReturn(stuff).when(serviceA).method();
Mockito.doReturn(otherStuff).when(serviceB).method();
You need to mark your object as Spy or explicitly create a Spy object for it using MyClass objA=null;
MyClass spy_objA=Powermockito.spy(objA)
doReturn(what_you_want).when(spy_objA).method()
Edit: Can find a similar question you may want to check
How to mock another method in the same class which is being tested?
I would like to test that my custom exception is thrown when I call a method like that:
private MyObject queryDatabase(String request, String end){
HttpEntity myEntity = new NStringEntity(request, ContentType.APPLICATION_JSON)
Response response = restClient.performRequest("GET", end,Collections.emptyMap(), myEntity)
MyObject myObject = mapper.readValue(response.getEntity().getContent(), MyObject.Class);
if(myObject.getFunctions().isEmpty()){
throw new EmptyResultException("Empty result");
}
return myObject;
}
My EmptyResultException Class :
#ResponseStatus(value=HttpStatus.NO_CONTENT)
public Class EmptyResultException() extends RuntimeException(){
...
}
I'm just starting with JUnit and I have tried :
#Mock MyService myservice;
#Test(expected=EmptyResultException.class)
public void shouldReturnException() {
when(myService.queryDatabase(anyString(),anyString())).thenReturn(new MyObject());
}
It's not working. The behavior I want to try is in private method. It seems I should use Powermock for such cases. However, I have read it is not good to test private method so I would like to change my method to public. Any help please?
EDIT : My full implementation :
I have a Restcontroller :
#RestController
#RequestMapping...
public class MyController {
#Autowired
MyService myService;
#RequestMapping...
public MyObject findObject(#Valid DtoParameters parameters){
return myService.executeQuery(parameters);
}
}
And in myService Class :
#Service
public class MyService{
public MyObject executeQuery(DtoParameters parameters){
return
queryDatabase(parameters.buildRequest(),parameters.buildEnd());
}
}
If your class under test is MyService, it shouldn't have a #Mock.
I don't know your whole implementation, but let's assume MyService have injected dependencies (like your mapper)
First I would mock the mapper and inject it in MyService:
#Mock
private ObjectMapper mapper;
#InjectMocks
private MyService myService;
For this to work, your test class need to use the mockito runner. You can annotate your class with this:
#RunWith(MockitoJUnitRunner.class)
The mocks will be injected into MyService.
Now you can mock your mapper to return an empty object:
when(mapper.readValue(any(),any())).thenReturn(new MyObject());
myService.queryDatabase("request", "end")
when calling queryDatabase, this should call the mock inside.
If you were trying to test your rest controller, it is a different way. What I suggested is a unit test on MyService. If you want to test the controller, you should do it with a SpringRunner, SpringBootTest and MockMvc. But first, unit test your service, and add other tests on your controller later. For the controller, you would annotate MyService with #MockBean and throw, or Autowire it and #MockBean the mapper inside to return an empty object like the unit test.
Check this: https://spring.io/guides/gs/testing-web/
old answer:
You could change your method to protected, assuming your test is in the same package as the class you are testing, you will be able to mock it.
To mock your method, you need to write it like this:
when(myService.queryDatabase(anyString(),anyString())).thenThrow(EmptyResultException.class);
You forgot to use the when method to wrap your call.