I decided to use ** JUnit + Mockito + PowerMock ** in the project I'm currently working on. In the first place, everything is unknown to me, who has never touched JUnit itself.
Even if you try gg with "** Mockito **", there are few articles that explain that people with zero knowledge can use it immediately. Or rather ** I don't have much Japanese! ** ** It's hard to understand without explanation in Japanese. ..
So, I'm writing this article for me who didn't know anything because I finally swallowed a little recently.
This time is ** Mockito ** edition.
In particular, I will write about the case where you want to mock a method of a class different from the class under test.
First of all, there are many things that Mockito cannot do. It's not all-purpose, and the methods that can be mocked are limited. I can't mock it
-** private method ** -** static method ** -** protected method ** -** Instantiation (new) **
These are the above four types. (Perhaps) I also think that abstract classes couldn't be mocked. (Perhaps)
Otherwise, you can basically mock it with mockito (maybe).
To mock the above four, you have to use PowerMock
separately from Mockito.
First, mock the class to call the mocked method. There are ** 2 types of mocking methods **. Only one of them is fine.
** ① Directly under the class @ Mock
**
** ② Use the mock ()
method **
Java
public class TestClass {
//① Directly under the class@Declaring a mock instance in Mock
@Mock
private Entity entity; //This is a declaration only, no mock object is created
@Test
public void test001() {
// ② mock()Use method
Entity entity = mock(Entity.class); //This alone will create a mock object
}
}
In case of ** ① **, it is necessary to initialize separately from this declaration. ** ② ** mock the class every time in the test class. It does not need to be initialized.
In the case of @ Mock
of ** ① **, the mock object has not been created yet, so it is necessary to ** initialize **.
Java
public class class() {
// @Mock pattern
@Mock
private ResultEntity entity;
@Before // @Annotate Before and execute each test method before execution.
private void initMocks() {
MockitoAnnotations.initMocks(this); //Initialization magic
}
}
I think the ** ① ** method is effective when ** there are multiple test cases and the class you want to mock appears many times **.
Use the @InjectMocks
annotation to inject a mock into the tested class directly under the test class.
public class TestClass {
@Mock
Entity entity; //Mocked class
@InjectMocks
Human human; //Inject mock into the class under test
}
For the time being, it is possible to mock it and then test it. When getting coverage, ** it will not be 100% unless the instance of the class under test is called **, so if you want to set coverage to 100%
@InjectMocks
Human human = new Human();
It's okay to write like this.
Now that we have mocked the class, we will actually mock the method for each case below.
public String
etc.
In this case, there are ~~ why ~~ ** 2 types ** of how to mock the method.
Mockito.when(Mock instance).Method(Arbitrary argument).thenReturn(Any return value);
//It will return this return value when the method of the mocked class is called
The method is now mocked, and the method is not actually executed and is just a mock that returns an arbitrary return value.
By the way, the head Mockito.
can be with or without it.
Since PowerMock
is written in the same way, ** if you use it at the same time, you need to use it properly **, so it will be easier to understand if you put it in your head.
Mockito.doReturn(Any return value).when(Mock instance).Method(Arbitrary argument);
//I'll return this return value when the method of the mocked class is called
Both ① and ② behave exactly the same. As explained below, ** then method may not be able to handle it **, so it seems that there is no mistake if you unify with do method.
public void
In this case, it can be described only by ** do method **.
Mockito.doNothing().when(Mock instance).Method(Arbitrary argument);
//It doesn't return anything, when a mock class method is called
There doesn't seem to be a method called thenNothing ().
Since the method is mocked, there is no need to verify it, but I think it will be necessary to verify that the arguments passed to the mocked ** method are correct **.
You can use ʻArgument Captor` in such a case.
ArgumentCaptor<Mold>variable= ArgumentCaptor.forClass(Mold.class);
// forClass()Create a container (variable) of that type with a method
If you pass the above variable as an argument when mocking the method, the argument actually passed will be captured and stored in the variable.
At that time, add the capture ()
method.
Mockito.doReturn("Return value").when(class).Method(variable.capture());
// forClass()Create a container (variable) of that type with a method
The variable now contains the arguments passed in the actual source.
variable.getValue(); // ①
variable.getAllValues().get(index); // ②
By using either of these methods, you can get the value according to the type of the variable.
** ① ** If you want to verify only one argument, you can get the information stored by the getValue ()
method.
** ② ** ArgumentCaptor can be passed to ** arguments many times and can store as many results as there are arguments **. (Only for the same type.)
In that case, it is stored in the form of an array, so get all the values with the getAllValues ()
method. You can get the value of one of them with get (index)
.
Actually, if you reuse variables, it will be difficult to determine what number is in which argument, so basically ** declare the contents of ʻArgumentCaptor` as many as the number of arguments ** I think it's better to do it.
ArgumentCaptor<String> str = ArgumentCaptor.forClass(String.class);
Mockito.doReturn("Return value").when(Class).getStr(str.capture());
assertTaht(str.getValue(), is(Expected value of argument));
I think it will look like this.
When you mock a method, it doesn't actually call that method, so you may need to ** verify that the mocked method is called properly **.
The verify ()
method is used at that time.
Mockito.verify(Mock instance, times(index)).Mock method(argument);
You can verify how many times the method has been called by passing the expected value as the mock instance as the first argument of the verify ()
method, the times ()
method as the second argument, and int as the argument.
What do you mean
Mocking a method without a return value is as described in [For a public void method with no return value](# For a public void method with no return value).
If you want to verify the number of method calls, you don't have to do both doNothing ()
and verify ()
, you can do both at the same time with just ** verify ()
. ** **
Rather than doing it at the same time, it means that it has been mocked as a method with no return value at the time of ** verify () **.
The only caveat is that ** methods with a return value cannot be mocked with verify () **.
This is because verify () ** cannot mock the return value **.
// doNothing()Even if you do not mock with, this is ok
Mockito.verify(Mock instance, times(index)).Mock method();
By the way, in the above case + if you want to verify the argument
// doNothing()Even if you do not mock with, this is ok
Mockito.verify(Mock instance, times(index)).Mock method(variable.capture());
By doing so, the arguments can also be stored at this time.
If you remember these, I think you will be able to fight to some extent. I plan to write mocking of other methods of the same class and mocking of new in the future.
[Java] How to drink Mockito (Introduction)
Recommended Posts