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)
}
Related
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()));
}
}
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();
}
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);
}
public interface Dummy {
public returnSomething doDummyWork(arg1, agr2);
}
public class A implements Dummy {
#AutoWired
PrintTaskExecutor printTaskExecutor;
public returnSomething doDummyWork(arg1, agr2) {
callingVoidMethod();
return something;
}
public void callingVoidMethod() {
printTaskExecutor.printSomething(arg1, arg2);
}
}
public class testDummy {
#Autowired
Dummy dummyA//this bean is configured in ApplicationContext.xml and it works fine.
#Mock
PrintTaskExecutor printaskExecutor;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
printaskExecutor = Mockito.mock(PrintTaskExecutor.class);
Mockito.doNothing().when(printaskExecutor).printSomething(anyString(), anyString());
}
#Test
Public void testA
{
Dummy.doDummyWork(arg1, arg2);//I m giving actual arguments
//instead of moocking it calls the original method.
Mockito.verify(printaskExecutor, times(1)).printSomething(anyString(), anyString());
}
}
I have an autowired TaskExecutor in the class I m testing and I want to mock it.I have tried this in my code and It calls the actual method instead of do nothing and in the verify it errors out saying no interactions happened. How should I handle this situation?
I try to avoid using Mockito and Bean Containers together in one test. There are solutions for that problem. If you use Spring you should use #RunWith(SpringJUnit4Runner.class). More on this subject: Injecting Mockito mocks into a Spring bean
The clean way: Actually your class testDummy does not test Dummy but A. So you can rewrite your class in following way:
public class testA {
#Mock
PrintTaskExecutor printTaskExecutor;
#InjectMocks
A dummyA;
...
BTW: #Mock together with initMocks(this) and printaskExecutor = Mockito.mock(PrintTaskExecutor.class); do the same, you can skip the latter statement.
I have to test the following class, with an autowired object:
public class Provider {
#Autowired
private Service service;
public Provider() {}
public Provider(final Service service) {
this.service = service;
}
// Other code here
}
I created my test as follows:
#RunWith(PowerMockRunner.class)
public class ProviderTest {
#Mock(name="service") Service service;
#Mock Score score;
#InjectMocks Provider provider = new SearchResultProvider();
#Before
public void setup() {
when(service.process()).thenReturn(score);
}
#Test
public void my_test() {
provider.execute(); // It fails, because service.process() returns null
// Other code here
}
// Other tests here
}
However, when I run the test, it fails. Everything is fine, except the clause when(...) that seems to be ignored.
That causes the test to fail on the call to provider.execute(). Inside this function the call to service.process() is executed and then I would expect a "score mock" to be returned. But a null value is returned instead.
What have I done wrong?
The sample code show no need for powermock, I suppose there's PowerMock because some code is final. But the test don't prepare the classes to be definalized.
I will suppose the code with a final method is the Service
public class Service {
public final Score process() {
throw new NullPointerException("lol");
}
}
Then the code won't pass, unless the test prepares the classes to be definalized :
#RunWith(PowerMockRunner.class)
#PrepareForTest(Service.class)
public class ProviderTest {
...
}