I want to test requestListServiceImpl this class.It contains requestListDao.
RequestListServiceImpl Code
#Override
public PageInfo<RequestList> getAllRequest(int startPage, int pageSize, String accountName,String userName) {
PageHelper.startPage(startPage, pageSize);
List<RequestList> list=requestListDao.getAllRequest(accountName,userName);
for(RequestList requestList:list) {
switch (requestList.getStatus()) {
case "0":
requestList.setStatus("Waiting");
break;
case "1":
requestList.setStatus("Closed");
break;
case "2":
requestList.setStatus("Cancel");
break;
default:
requestList.setStatus("NAN");
break;
}
}
PageInfo<RequestList> pageInfo = new PageInfo<RequestList>(list);
return pageInfo;
}
#Override
public void createRequest(RequestList requestList) {
Integer coount=requestListDao.getTime(requestList.getCreateName());
// AWSSnsUtil.sendMassageToSns(requestList.getAccountName());
requestList.setTime(++coount);
requestListDao.createRequest(requestList);
}
Test Code:
#InjectMocks
RequestListServiceImpl requestListServiceImpl;
#Mock
RequestListDao requestListDao;
#Before
public void setup(){
MockitoAnnotations.openMocks(this);
}
#Test //it's ok
public void testGetAllRequest() throws Exception {
RequestList r=new RequestList();
r.setStatus("0");
when(requestListDao.getAllRequest(anyString(), anyString())).thenReturn(Arrays.<RequestList>asList(r));
PageInfo<RequestList> res=requestListServiceImpl.getAllRequest(1,1,"1","1");
Assert.assertNotNull(res);
}
#Test //this test is error, the error is requestListServiceImpl is not mock.
public void testCreateRequest() throws Exception {
when(requestListDao.getTime(anyString())).thenReturn(0);
RequestList r=new RequestList();
r.setCreateName("demo");
requestListServiceImpl.createRequest(r);
verify(requestListServiceImpl).createRequest(r);
}
Error info
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type RequestListServiceImpl and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
When i change #InjectMocks to #Mock, The second test it's ok ,but first test it's error.
I need add to a stubbing when(requestListServiceImpl.getAllRequest(anyInt(),anyInt(),anyString(),anyString())).thenReturn(new PageInfo<>());
I don't know how to do it,
Is injectmocks necessary?
Here:
verify(requestListServiceImpl)
And
#InjectMocks
RequestListServiceImpl requestListServiceImpl;
The message is pretty clear: you verify mock objects that Mockito created for you.
#InjectMocks does not create mocks. It rather injects mocks that you have in your test class into a real object.
So, what is necessary here: read the manual or a tutorial. Meaning: don't start with Mockito by applying it immediately to your project. Instead, step back, and look at simple examples to understand how it is supposed to be used.
In your current setup: requestListServiceImpl is a real object. So you should check if that class offers you methods to verify its internal status. You triggered some action on it, but because it is a real object, Mockito doesn't know what you did. But how to actually solve this depends on YOUR code base.
You want to test requestListServiceImpl you should use #InjectMocks so mockito calls the real method on requestListServiceImpl. When you use #Mock, the method will by default not be invoked.
#InjectMocks will be the same as if you create it yourself with new requestListServiceImpl(mock(requestListDao))
When you use verify(mock).someMethod(); you have to pass a mock to that method, not #InjectMocks.
You want to verify if a certain method is called on a mock inside your class under test(requestListServiceImpl).
Instead of #InjectMocks there is also #Spy, which will kinda do both, you can mock methods in requestListServiceImpl but also call the real method.
Related
I am trying to create a unit test for the following method that calls another private method:
public CommandDTO create(final LabelRequest request) {
return saveLabel(new Label(), request);
}
private CommandDTO saveLabel(final Label label, final LabelRequest request) {
label.setName(request.getName());
final Label saved = labelRepository.saveAndFlush(label);
return CommandDTO.builder().uuid(saved.getUuid()).build();
}
It returns "nullpointer exception for the saved parameter as I did not mock in in my test.
Here is the Unit Test. I added 2 question as comment (Q1 and Q2). Could you please clarify me what is wrong?
#RunWith(MockitoJUnitRunner.class)
public class LabelServiceImplTest {
#Mock
private LabelRepository labelRepository;
#InjectMocks
private LabelServiceImpl labelService;
#Captor
ArgumentCaptor<Label> labelCaptor;
#Test
public void test_create {
// Q1: I am not sure if the following parts are needed
final LabelRequest request = new LabelRequest();
request.setName("Label Name");
final Label label = new Label();
label.setName(request.getName());
// Q2: I think there is no need to mock saveAndFlush method.
// But in this scene it returns "nullpointer exception"
when(labelRepository.saveAndFlush(any())).thenReturn(label);
CommandDTO result = labelService.create(request);
Mockito.verify(labelRepository).saveAndFlush(labelCaptor.capture());
final Label value = labelCaptor.getValue();
// then make necessary assertions
}
}
F I R S T
I think that you only declared your mocks but never defined/created them. There's basically three ways to do so:
1) mockito extension
The convenient way in JUnit 5 is to use the MockitoExtension:
#ExtendWith(MockitoExtension.class)
public class LabelServiceImplTest {
// declare mocks, spies and captors ...
// system under test
#InjectMocks
LabelService sut;
}
Nothing else should be needed now.
Mind that by #InjectMocks you instruct Mockito to create your system under test and inject the mocks. You may as well do that manually, e. g. by injecting mocks into the SUT's constructor. I prefer that way to have more control over the configuration of my SUT.
2) MockitoAnnotations.openMocks(testclass)
This method will inject mocks into the given object:
public class LabelServiceImplTest {
// declare mocks, spies and captors ...
// system under test
#InjectMocks
LabelService sut;
#BeforeEach
void setup() {
MockitoAnnotations.openMock(this)
// ...
}
}
On JUnit 4 you'd use MockitoAnnotations.initMocks(…) instead.
3) the old school way
public class LabelServiceImplTest {
LabelRepository labelRepositoryMock = Mockito.mock(LabelRepository.class);
// ...
// system under test
LabelServiceImpl sut;
#BeforeEach
void setup() {
sut = new LabelService(labelRepositoryMock);
// ...
}
}
S E C O N D
Your questions …
1) Do you need to create the request and the label?
Yes. You call the service using the request and the mock returns the label. I would suggest you do not use the request's property to set up your label, use a String literal instead.
2) Do you need to mock the saveAndFlush() method?
Yes. This is the part where you configure your SUT's environment to behave in a predictable way.
You might consider postfixing your mocks, spies and captors by: "Mock", "Spy" and "Captor".
You might also consider calling your system under test "sut".
#Mock
private LabelRepository labelRepositoryMock;
#Captor
ArgumentCaptor<Label> labelCaptor;
// system under test
#InjectMocks
private LabelServiceImpl sut;
This makes the test code more readably, I think.
As the title states, I can call verifyPrivate but it always gives me success even if I pass the wrong parameters to it.
Real example
#RunWith(PowerMockRunner.class)
#PrepareForTest({MyService.class})
public class MyServiceTest {
#InjectMocks
MyService service;
#Mock
OperationSivRepo operationSivRepo;
#Test
public void getNbInscriptions_should_call_getNbOperationsSiv_with_OPERATION_INSCRIPTION_GAGE() throws Exception {
// GIVEN
Role role = Role.ADMINISTRATEUR;
String operator = "operator";
SivDto sivDto = new SivDto();
// WHEN
service.getNbInscriptions(operator, role, sivDto);
// THEN
verifyPrivate(service).invoke("privateMethod", operator, Role.ADMINISTRATEUR, sivDto);
}
}
Now this code will succeed, even if I do something like
// THEN
verifyPrivate(service).invoke("privateMethod", "other string", Role.USER, new SivDto());
Maybe I'm missing something but I just can't figure it out.
Firstly. Did you put a debug point in privateMethod and see how many times it is getting called? This would have given you some hint.
It is getting called two times. Once when you call
service.getNbInscriptions(operator, role, sivDto);
and once when you use
verifyPrivate(service).invoke("privateMethod", operator, Role.ADMINISTRATEUR, sivDto);
Second time since it is getting called with the arguments you passed to invoke method, the tests always succeed.
Use Spy instead of Mock
Instead of
#InjectMocks
MyService service;
Use
#Spy
MyService myservice = new MyService(operationSivRepo)
Wiht this, second invocation to the method is not made and arguments are verified properly.
I was learning mockito and I understood the basic usages of the above mentioned functions from the link.
But I would like to know whether it can be used for any other cases?
doThrow : Basically used when you want to throw an exception when a method is being called within a mock object.
public void validateEntity(final Object object){}
Mockito.doThrow(IllegalArgumentException.class)
.when(validationService).validateEntity(Matchers.any(AnyObjectClass.class));
doReturn : Used when you want to send back a return value when a method is executed.
public Socket getCosmosSocket() throws IOException {}
Mockito.doReturn(cosmosSocket).when(cosmosServiceImpl).getCosmosSocket();
doAnswer: Sometimes you need to do some actions with the arguments that are passed to the method, for example, add some values, make some calculations or even modify them doAnswer gives you the Answer<?> interface that being executed in the moment that method is called, this interface allows you to interact with the parameters via the InvocationOnMock argument. Also, the return value of answer method will be the return value of the mocked method.
public ReturnValueObject quickChange(Object1 object);
Mockito.doAnswer(new Answer<ReturnValueObject>() {
#Override
public ReturnValueObject answer(final InvocationOnMock invocation) throws Throwable {
final Object1 originalArgument = (invocation.getArguments())[0];
final ReturnValueObject returnedValue = new ReturnValueObject();
returnedValue.setCost(new Cost());
return returnedValue ;
}
}).when(priceChangeRequestService).quickCharge(Matchers.any(Object1.class));
doNothing: (From documentation)
Use doNothing() for setting void methods to do nothing. Beware that void methods on mocks do nothing by default! However, there are rare situations when doNothing() comes handy:
Stubbing consecutive calls on a void method:
doNothing().
doThrow(new RuntimeException())
.when(mock).someVoidMethod();
//does nothing the first time:
mock.someVoidMethod();
//throws RuntimeException the next time:
mock.someVoidMethod();
When you spy real objects and you want the void method to do nothing:
List list = new LinkedList();
List spy = spy(list);
//let's make clear() do nothing
doNothing().when(spy).clear();
spy.add("one");
//clear() does nothing, so the list still contains "one"
spy.clear();
It depends on the kind of test double you want to interact with:
If you don't use doNothing and you mock an object, the real method is not called
If you don't use doNothing and you spy an object, the real method is called
In other words, with mocking the only useful interactions with a collaborator are the ones that you provide. By default functions will return null, void methods do nothing.
To add a bit to accepted answer ...
If you get an UnfinishedStubbingException, be sure to set the method to be stubbed after the when closure, which is different than when you write Mockito.when
Mockito.doNothing().when(mock).method() //method is declared after 'when' closes
Mockito.when(mock.method()).thenReturn(something) //method is declared inside 'when'
A very simple example is that if you have a UserService that has #Autowired jpa resposiroty UserRepository
...
class UserService{
#Autowired
UserRepository userRepository;
...
}
then in the test class for UserService you will do
...
class TestUserService{
#Mock
UserRepository userRepository;
#InjectMocks
UserService userService;
...
}
#InjectMocks tells the framework that take the #Mock UserRepository userRespository; and inject that into userService so rather than auto wiring a real instance of UserRepository a Mock of UserRepository will be injected in userService.
If you are testing a logic class and it is calling some internal void methods the doNothing is perfect.
I have got a problem with testing how many times concrete methods (IFunction in the Operation instance) is invoked.
According to:
http://easymock.org/user-guide.html#mocking-annotations
http://www.ibm.com/developerworks/library/j-easymock/
How to use EasyMock expect
I wrote something as:
class Operation{
public double[] calculateSth(IFunction function, int [] t){
for(int i=0 ; i<5 ; i+=1)
function(t, new int[]{1,2,3});
return new double[]{1,2,3};
}
}
interface IFunction{
double f(int[] a, int[]b);
}
class ConcreteF implements IFunction{
double f(int[]a, int[]b){
return 5;
}
}
And my test class:
#TestSubject
Operation op;
#Mock
IFunction function;
#Before
public void setUp() throws Sth{
op=new Operation();
function = EasyMock.createMock(IFunction.class);
}
#Test
public void howManyTimes(){
EasyMock.expect(function.f(EasyMock.notNull(), EasyMock.notNull())
)
.andReturn((double)EasyMock.anyDouble()).times(3);
EasyMock.replay(function);
op.calculateSth(function, new double[]{0,0,0});
//verify
EasyMock.verify(function);
}
Result:
java.lang.NullPointerException
at org.easymock.internal.Injector.injectMocks(Injector.java:80)
at org.easymock.EasyMockSupport.injectMocks(EasyMockSupport.java:624)
at org.easymock.EasyMockRunner.withBefores(EasyMockRunner.java:50)
It's my first time using easymock and i don't know how to fix it ;/
I'll answer this question without going into the details of whether the original method does anything useful (the code doesn't even compile anyway), let alone the test method.
#TestSubject Operation op;
This line is a suspect. I realize that you are instantiating it in the #Before annotated setUp method, but it looks like the Easymock tries to inject the mocks (the ones annotated with #Mock) before it does anything (and understandably so) and blows up since the reference is null at that point.
The annotation support introduced in v3.2 is also seen as a way to eliminate the need for setUp method. But you seem to be mixing both and using it wrongly. Choose one or the other - I'd recommend you to use the annotations.
Quoting the Easymock user guide (this user guide is as good as it can ever be, so be sure read this up before using the library),
#RunWith(EasyMockRunner.class)
public class ExampleTest {
#TestSubject
private ClassUnderTest classUnderTest = new ClassUnderTest(); // 2
#Mock
private Collaborator mock; // 1
#Test
public void testRemoveNonExistingDocument() {
replay(mock);
classUnderTest.removeDocument("Does not exist");
}
}
The mock is instantiated by the runner at step 1. It is then set by
the runner, to the listener field on step 2. The setUp method can be
removed since all the initialization was done by the runner.
I am having some troubles passing a dependency while unit testing with JUnit.
Consider these pieces of code:
This is the dependacy injecton into the class which i want to test, lets call it Controller.
#Inject private FastPowering fastPowering;
And this is the unit test:
#RunWith(MockitoJUnitRunner.class)
public class ControllerTest {
#Mock
FastPowering fastPower;
#InjectMocks
Controller controller;
#Test
public void test() {
assertEquals(
(controller.computeAnswer(new BigDecimal(2), 2)).longValue(),
(long) Math.pow(2, 2));
}
}
It seems that fastPower is null, please explain how to fix that.
Null pointer exception , because of calling the #injected field (fastPower) inside the .computeAnswer method)
Edit:
Solved i should have read about the difference between #Mock and #Spy...
Due to a lot of comments I am adding some more context to the solution
The difference is that in mock, you are creating a complete mock or fake object while in spy, there is the real object and you just spying or stubbing specific methods of it. While in spy objects, of course, since it is a real method, when you are not stubbing the method, then it will call the real method behavior.
If fastPower is annotated as #Mock it's methods are dummy, yet controller.computeAnswer depends on them to compute. One must provide behaviour.
If spy is used without stubbing then the real implementation of fastPower is being executed which eventually returns desired value.
Another option is to use a real FastPowering instance
https://github.com/mockito/mockito/wiki/Using-Spies-(and-Fakes)
https://github.com/mockito/mockito/wiki/Mocking-Object-Creation
And some stackoverflow thread outlining the difference Mocking vs. Spying in mocking frameworks
Short Answer: Replace #Mock with #Spy and should be working fine
Use MockitoAnnotations.initMocks to initiate the #Mock and #InjectMocks objects. Your test would look something like:
#Mock
FastPowering fastPower;
#InjectMocks
Controller controller;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
....
}
After debugging I found a reason. This is because of the org.powermock.core.MockRepository#instanceMocks collection. It doesn't contain a mock for a field with #InjectMocks annotation (Controller controller in your case).
To solve it try to use the #Spy annotation in the field declaration with initializing of them and #PrepareForTest above the class declaration:
#PrepareForTest(Controller.class)
#RunWith(MockitoJUnitRunner.class)
public class ControllerTest {
#Mock
FastPowering fastPower;
#Spy
#InjectMocks
Controller controller = new Controller();
#Test
public void test() {
//...
}
}
In my case it helped. Using of the Mockitoannotations.initMocks(this) method is not required, it doesn't affect the result.
I fixed this by removing the extraneous new instance I was creating in my #Before method (see example below). It was also fixed by moving MockitoAnnotations.initMocks(this) after initializing myClass, but since Mockito created myClass anyway, that solution was inferior.
// Note - you may need #mock(name="foo") to help mockito differentiate props
// if they have the same type
#mock
private Thing something;
#InjectMocks
private MyClass myClass;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this); // Moving this below the next line fixed it...
myClass = new MyClass() // But just remove this line and let Mockito do the work
}
Useful to note that the use of MockitoAnnotations.initMocks(this); needs to come at the end of your #Before/setUp() method.
If it is at the top of your setUp() then it may cause other mocked classes to not be initialised.
I ran into this error myself just now and placing .initMocks at the end of my #Before solved my issue.
I was using the wrong #Test annotations, If you want to use #InjectMocks and #Mock in your Mockito Test, then you should
add #ExtendWith(MockitoExtension.class) annotation on your test class
annotate your test methods with #Test (org.junit.jupiter.api.Test) and not the #Test (org.junit.Test) annotation. be careful with the import that you are using for this annotation.
This works on mockito-core:3.6.28
2 more things to check:
1. Mocking the behaviours of fastPower. What should this mocked object return, when it methods are called? i.e. when(fastPower.doSomething()).thenReturn(some_kind_of_object);
2. Check if the controller.computeAnswer() does not return NULL for the input of new BigDecimal(2), 2)).longValue(), (long) Math.pow(2, 2).