Mockito. How to mock abstract method call in class under test? - java

I have Test class for controller. I need to inject autowired field. And mock method of Controller's super class (I have no possibility to refactor this situation)
public class ControllerTest {
#Mock
Service service;
#InjectMocks
Controller controller;
#Test
public vois test() {
controller.process();
}
}
In process() method service is called and superclass's method, too.
I tried to init my controller in test in this way
new Controller() {
#Override
superMethod() {
//do nothing
}
}
But I cannot inject service mock in this case due to setter is missing. I can do it with reflection, but maybe someone knows more elegant solution?

If you are using annotations, you must to put #RunWith(MockitoJUnitRunner.class) above the ControllerTest or create setUp method like this:
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
Hope this help.

Related

NullPointerException when doNothing() is called on Junit Mockito

I am writing a my unit test using Mockito but I am facing some error stubbing a method in the same class as my test class.
So basically, I am testing my service class MyService.class(Subject being tested) and this is how I am declaring my Mocks and #InjectMocks.
I am facing a null pointer whenever i hit the checkUserBackground() method when I am using doNothing() because the method returns void. I have also tried using verify() but I am getting error saying "Wanted but not invoked".
How do I get pass this error? Been stuck for 13 hours, appreciate some help thanks!
#ExtendWith(MockitoExtension.class)
#MockitoSettings(strictness = "Strictness.LENIENT")
class MyServiceTest {
#InjectMocks
private MyService myService;
#Test
void testCreateUser() {
User user = new User();
user.setAge(25);
user.setName(Jack);
Mockito.doNothing().when(myService).checkUserBackground(user.getName(), true);
assertEquals(myService.createUser().getName(), "Jack");
}
}
This is the actual Service class:
class MyService() {
public static void createUser(User user) {
checkUserBackground(user.getName(), true); //Null Pointer here
}
public void checkUserBackground(String name, Boolean newUser){
//some logic which doesnt matter
}
}
Annotation #InjectMock is for dependency injection - its real class bean. But later in method you try mock method of injected bean.
In your case will be enougth when you add method instead annotation:
#Before
public void init() {
myService = Mockito.mock(MyService.class)
}

Unable to mock a method which takes an interface

I have a service in my Spring Boot Project in which i have method which takes an interface.
interface IT {}
class AService {
public String method(IT it) {}
}
I have two classes which implements that interface.
class AIT implements IT {}
class BIT implements IT {}
I am using this service method in some other service passing the AIT/BIT class object according to my need.
Now, I am writing the test cases for other service mocking the Service
public class OtherServiceTests {
#MockBean
private Service service;
#Before
public void setUp() {
// none of these mocks working
Mockito.when(service.method(Mockito.any()))
.thenReturn("");
Mockito.when(service.method(Mockito.any(IT.class)))
.thenReturn("");
Mockito.when(service.method(Mockito.any(BIT.class)))
.thenReturn("");
Mockito.when(service.method(Mockito.any(AIT.class)))
.thenReturn("");
// all returing to NullPointerException
otherService = new OtherSerice();
}
}
None of these mocks are working for this method only. Other mocks are working fine. It is returning NullPointerException which makes the tests fail.
I am new to testing using mockito. If anyone can guide me for this solution than this will be very helpful for me.
Mock is not initialized and the annotation #MockBean should be replaced with #Mock.
Try to change it like this:
public class AServiceTest {
#Mock
AService service;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void myTest(){
Mockito.when(service.method(Mockito.any())).thenReturn("");
assertEquals("", service.method(new AIT()));
}
}

Test a service in Spring with a Mock, What I'm doing wrong?

I have a Spring-boot project, in witch I have controller, service and mapper layer. Now I want to test a service and I want to mock the mapper. I do it in this way:
Test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(Application.class)
#Transactional
public class SomeServiceTest extends AbstractTransactionalJUnit4SpringContextTests {
#Mock
private AMapper aMapper;
#Autowired
#InjectMocks
AService aService;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
executeSqlScript("classpath:insertSomeData.sql", false);
}
#Test
public void testMethod() throws Exception {
//prepareSomeData
aService.callMethod(someData);
verify(aMapper).callTheRightMethod(rightObject);
}
And the service:
#Service
#Transactional(readOnly = true)
public class AServiceImpl implements AService {
#Autowired
BMapper bMapper;
#Autowired
CMapper cMapper;
#Override
#Transactional(readOnly = false)
public SomeReturnObject callMethod(SomeData someData)throws Exception {
//some execution to obtain aResult
if(true){
aMapper.callTheRightMethod(aResult);}
else
aMapper.callWrongMethod(aResult);
}
Now when I execute the test the result is:
Wanted but not invoked:
aMapper.callTheRightMethod{..}
Actually, there were zero interactions with this mock.
When i debug then I see that the method is called, but probably it's the wrong mapper (not the mocked). Have you some tips to figure out that issue?
I can't see the mock interaction recording here. It should come before the actual invocation. It should be something like this.
Mockito.when(aMapper.callTheRightMethod(Mockito.any()).thenReturn(rightObject);
The flow should be like this. Firstly record the mocks, then perform actual invocation and finally verify the mock interactions. As above #Autowire is not needed for the test class. Please remove that too. Instead create a new instance of service class by passing some data through it's constructor. Hope this helps. Happy coding !
I don't exactly understand why would you start up spring context for testing just a service layer. Test only one layer at a time.
That's how I would address the problem. (If something does not compile, my apologies..writing from top of my head)
#RunWith(MockitoJUnit4ClassRunner.class)
public class SomeServiceTest {
#Mock
private AMapper aMapper;
#InjectMocks
AService aService = new AService();
#Test
public void testMethod() throws Exception {
// given
Mockito.doReturn(aResult).when(aMapper).getAResult();
// when
aService.callMethod(someData);
// then
verify(aMapper).callTheRightMethod(rightObject);
}

How to AutoWire spring beans when using Mockito and Junit?

I am trying to set up my class to be used in Junit.
However when I try to do the below I get an error.
Current Test Class:
public class PersonServiceTest {
#Autowired
#InjectMocks
PersonService personService;
#Before
public void setUp() throws Exception
{
MockitoAnnotations.initMocks(this);
assertThat(PersonService, notNullValue());
}
//tests
Error:
org.mockito.exceptions.base.MockitoException:
Cannot instantiate #InjectMocks field named 'personService'
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null
How can I fix this?
You are not mocking anything in your code. #InjectMocks sets a class where a mock will be injected.
Your code should look like this
public class PersonServiceTest {
#InjectMocks
PersonService personService;
#Mock
MockedClass myMock;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Mockito.doReturn("Whatever you want returned").when(myMock).mockMethod;
}
#Test()
public void testPerson() {
assertThat(personService.method, "what you expect");
}
Another solution is to use #ContextConfiguration annotation with static inner configuration class like so:
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class PersonServiceTest {
#Autowired
PersonService personService;
#Before
public void setUp() throws Exception {
when(personService.mockedMethod()).thenReturn("something to return");
}
#Test
public void testPerson() {
assertThat(personService.method(), "what you expect");
}
#Configuration
static class ContextConfiguration {
#Bean
public PersonService personService() {
return mock(PersonService.class);
}
}
}
Anyway, you need to mock something that the method you want to test uses inside to get desired behaviour of that method. It doesn't make sense to mock the service you're testing.
You're misunderstanding the purpose of the mock here.
When you mock out a class like this, you are pretending as if it's been injected into your application. That means you don't want to inject it!
The solution to this: set up whatever bean you were intending to inject as #Mock, and inject them into your test class via #InjectMocks.
It's unclear where the bean you want to inject is since all you have is the service defined, but...
#RunWith(MockitoJUnitRunner.class);
public class PersonServiceTest {
#Mock
private ExternalService externalSvc;
#InjectMocks
PersonService testObj;
}
If I am not mistaken...the thumb rule is you cannot use both together..you either run unit test cases with using MockitojunitRunner or SpringJUnitRunner you cannot use both of them together.

Injection of a mock object into an object to be tested declared as a field in the test does not work using Mockito?

I have a class and I am injecting a proxy into my service.
Service service
{
private ServiceProxy proxy;
public Service(ServiceProxy proxy)
{
this.proxy = proxy;
}
}
The test for it is:
ServiceTest
{
#Mock
ServiceProxy mockProxy;
Service service = new Service(mockProxy);
}
If I initialize my class like this I always get a NPE when I want to use the service object. Why does Mockito do this? What is an easy way around this instead of declaring it in each and every test?
Provided you are using Mockito version 1.9.0 or later, the best way to achieve what you want is like this:
#RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
#Mock
private ServiceProxy proxy;
#InjectMocks
private Service service;
#Test
public void test() {
assertNotNull(service);
assertNotNull(proxy);
}
}
First thing is the #RunWith(MockitoJUnitRunner.class) declaration which will cause #Mock and #InjectMocks annotation to work automatically without any explicit initialization. The second thing is that starting with Mockito 1.9.0 #InjectMocks annotation can use the Constructor injection mechanism which is the best option for your Service class.
Other options for #InjectMocks are Setter injection and Field injection (see docs BTW) but you'd need a no argument constructor to use them.
So summarizing - your code cannot work because:
you are not using the MockitoJUnitRunner nor MockitoAnnotations.initMocks(this) so #Mock annotation takes no effect
even if above were satisfied your example would fail because mockProxy would be initialized after the test is constructed and your service is tried to be initialized during the test class construction, hence it receives null mockProxy reference.
If for some reason you don't want to use #InjectMocks, the only way is to construct your Service object within the test method body or within the #Before annotated setUp method.
Write your test class as this, which will initialize Service with a mock of ServiceProxy:
class ServiceTest
{
#Mock
ServiceProxy mockProxy;
//This will inject the "ServiceProxy" mock into your "Service" instance.
#InjectMocks
Service service = new Service(mockProxy);
#Before
public void init() {
//This will initialize the annotated mocks
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
...
}
}

Categories

Resources