How to determine the Mock and injectMock objects in mockito? - java

I am beginner with Mockito framework, and i have some problems in determining the mocked and injected mocks objects, Actually I have the following structure in my project.
//WebService Interface
Interface WebService{
#Gateway(...)
public x call1(parameters);
}
//Class that implements another interface
Class A implements interfaceA{
#Autowired
WebService WS;
public void M1(){
.....
WS.call1(parameters);
.....
}
}
//Test Class
#Mock
#Autowired
WebService WS;
#InjectMock
#Autowired
A a;
#Before
setup(){
MockitoAnnotations.initMocks(this);
}
#Test
#Rollback(true)
#Transactional
public void Test() {
when(WS.call1(parameters)).thenReturn(x);
actualResult = a.M1();
assertNotNull(actualResult);
verify(WS, Mockito.times(1)).call1(parameters);
}
Are the Mocked and injected mock objects chosen correctly?
And if yes, i keep getting this exception message:
Wanted but not invoked:
WS.call1(
........
);
Actually, there were zero interactions with this mock.

You are using #Mock and #Autowired together. This doesn't make sense. You either mock or autowire your beans. Remove Autowiring
#Mock
WebService WS;
#InjectMock
A a;

Related

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()));
}
}

Mockito - underlying service is null

I have a Service A which autowired Service B and is using a method from Service B.
Service B autowired another Service C and is using a method from it.
I am writing a test for Service A and the test fails at the call where Service B is invoked.At this point Service C is null.
I have tried #Mock for Service B. Nothing seems to work. How can i successfully test this service which is failing on a service that it isnt explicitly autowiring.
//Service A
#Service
public class FileServiceImpl{
#Autowired
private FileNameServiceImpl fileNameService;
public void createFile(String fileName){
String targetFileName = fileNameService.getTargetFileName(fileName);
}
}
//Service B
#Service
public class FileNameServiceImpl{
#Autowired
private CustomDateService customDateService
public String getTargetFileName(String fileName){
return fileName + customDateService.getCustomDate();
}
}
//CustomDate - this is an interace. The Impl is in another package.
public interfaceCustomDateService{
public String getCustomDate();
}
I am trying to test FileServiceImpl , however it fails with a NullPointer Exception because customDateService is null.
Even though, FileServiceImpl is not calling customDateService.
This is what I have for test thus far:
#Category(UnitTest.class)
#RunWith(MockitoJUnitRunner.class)
public class FileServiceImplTest {
#Spy
#InjectMocks
private FileServiceImpl fileServiceImpl;
#Mock
private FileNameServiceImpl fileNameService;
#Before
public void init() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testFileName() {
String fileName = "test1.txt";
fileServiceImpl.createFile(fileName); // Test Fails here
Mockito.validateMockitoUsage();
}
As Shane eluded, this sounds like you're maybe integration testing.
If so, make sure the context of your test encompasses the autowired components.
You should post some code, as it's hard to know what exactly is going on here.
If you aren't integration testing, don't rely on autowiring, just construct new ServiceA manually passing in a mocked ServiceB.
Also make sure to initialise your mocks.
private ServiceA serviceA;
#Mock
private ServiceB serviceB;
#BeforeEach
public void setUp() {
MockitoAnnotations.initMocks();
serviceA = new ServiceA(serviceB);
}
EDIT:
First of all, as good practice you should favor constructor injection over field injection in Spring.
So set up the service classes with Autowired constructors.
Also, I'm pretty sure with a mockito Spy you have to initialise the class.
If you switch to use constructor Autowiring you can inject the mocks manually.
#Category(UnitTest.class)
#RunWith(MockitoJUnitRunner.class)
public class FileServiceImplTest {
#Spy
private FileServiceImpl fileServiceImpl;
#Mock
private FileNameServiceImpl fileNameService;
#Before
public void init() throws Exception {
MockitoAnnotations.initMocks(this);
fileServiceImpl = new FileServiceImpl(fileNameService);
}
#Test
public void testFileName() {
String fileName = "test1.txt";
fileServiceImpl.createFile(fileName); <-- now this shouldn't fail
Mockito.validateMockitoUsage();
}

How to inject mocks into a method two steps down from the tested class

I want to write a kind of an integration test of a class and the "lower" classes that it calls during operation. I want to mock the database connection that is called by the "lower" class, but I have not found a way to do this.
I have a class, that calls another class, that calls the database through jdbcTemplate. I want to inject a mock jdbcTemplate to the lower class, but I seem to be injecting it to a wrong instance of the class. The code follows this template:
#Component
public class A {
#AutoWired
B b
public String someMethod() {
b.otherMethod();
}
}
#Component
public class B {
#AutoWired
jdbcTemplate jdbctemplate
public String otherMethod() {
jdbctemplate.query(args);
}
}
The test is like follows:
#RunWith(MockitoJUnitRunner.Silent.class)
public class aTestClass {
#Mock
JdbcTemplate jdbcTemplate;
#InjectMocks
B b;
#InjectMocks
A a;
#Test
public void aTest() {
a.someMethod();
}
}
But when I run this test I get a NullPointerException at a.someMethod() - it seems that the B-object being called is null.
The problem is, that if I mock B, then it's not ever going to actually call jdbcTemplate since it is a mock.
Can anybody shed some light on how I could inject a mock jdbcTemplate to a B-object that is being called by A?
If you want an actual integration test:
1) Don't mock the template.. mock the entire repository.
2) You don't need #InjectMocks in an integration test. Spring does the DI.
3) As this is IT test you would need to use SpringRunner.class, not the MockitoJUnitRunner.class runner.
#RunWith(SpringRunner.class)
public class aTestClass {
#MockBean
B b;
#Autowired
A a;
#Test
public void aTest() {
a.someMethod();
}
}
For a unit test just mock the B and inject on A:
#RunWith(MockitoJUnitRunner.Silent.class)
public class aTestClass {
#Mock
B b;
#InjectMocks
A a;
#Test
public void aTest() {
a.someMethod();
}
}
Do not mock dependencies of dependencies in a unit test. You should not care about lower levels there.
After DuckDuckGoing a bit I managed to get the test working with Maciejs instruction. At first it did not work, but adding #Configuration to both the beans it did. Here is the code that worked for me:
#RunWith(SpringRunner.class)
public class aTestClass {
#MockBean
JdbcTemplate jdbcTemplate;
#Autowired
B b;
#Autowired
A a;
#Test
public void aTest() {
when(jdbcTemplate.query(args)).thenAnswer(whatyouwant));
a.someMethod();
}
#Configuration
#Import(A.class)
static class AConfig {
}
#Configuration
#Import(B.class)
static class BConfig {
}
}

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.

Categories

Resources