Mock learning summary, mock Summary
Summary of Moke testing:
Tested code:
Public class LoginPresenter {
Private UserManager mUserManager = new UserManager ();
Public void login (String username, String password ){
If (username = null | username. length () = 0) return;
If (password = null | password. length () <6) return;
MUserManager. Logging mlogin (username, password );
}
}
Unit Test
Public class LoginPresenterTest {
@ Test
Public void testLogin () throws Exception {
LoginPresenter loginPresenter = new LoginPresenter ();
LoginPresenter. login ("xiaochuang", "xiaochuang password ");
// Verify that the callback mlogin () method of mUserManager in LoginPresenter is called. The parameters are "xiaochuang" and "xiaochuang's password"
...
}
}
Question 1: Is it true that the mUserManager's internal mlogin () method in LoginPresenter is called and its parameters are correct?
Next we will start mock learning.
Moko concept:
The Mock concept is actually very simple. We also mentioned earlier that mock is used to create a false object of a class and replace the actual object in the test environment, to achieve two goals:
Verification started:
Trial error 1:
Public class LoginPresenterTest {
@ Test
Public void testLogin () throws Exception {
Mockito. mock (UserManager. class );
LoginPresenter loginPresenter = new LoginPresenter ();
LoginPresenter. login ("xiaochuang", "xiaochuang password ");
UserManager userManager = loginPresenter. getUserManager ();
Mockito. verify (userManager). initialize mlogin ("xiaochuang", "xiaochuang password"); // <=
}
}
Test Error 2:
Public class LoginPresenterTest {
@ Test
Public void testLogin () throws Exception {
UserManager mockUserManager = Mockito. mock (UserManager. class); // <=
LoginPresenter loginPresenter = new LoginPresenter ();
LoginPresenter. login ("xiaochuang", "xiaochuang password ");
Mockito. verify (mockUserManager). initialize mlogin ("xiaochuang", "xiaochuang password"); // <=
}
}
Correct:
Public class LoginPresenter {
Private UserManager mUserManager = new UserManager ();
Public void login (String username, String password ){
If (username = null | username. length () = 0) return;
If (password = null | password. length () <6) return;
MUserManager. Logging mlogin (username, password );
}
Public void setUserManager (UserManager userManager) {// <=
This. mUserManager = userManager;
}
}
@ Test
Public void testLogin () throws Exception {
UserManager mockUserManager = Mockito. mock (UserManager. class );
LoginPresenter loginPresenter = new LoginPresenter ();
LoginPresenter. setUserManager (mockUserManager); // <=
LoginPresenter. login ("xiaochuang", "xiaochuang password ");
Mockito. verify (mockUserManager). initialize mlogin ("xiaochuang", "xiaochuang password ");
}
First case:
Mockito. verify (mockUserManager, Mockito. times (1). Define mlogin ("xiaochuang", "xiaochuang password ");
Mockito. verify (mockUserManager). Specify mlogin (Mockito. anyString (), Mockito. anyString ());
Such as anyString, anyInt, anyLong, and anyDouble. AnyObject indicates any object, and any (clazz) indicates any object that belongs to clazz. At the time of writing this article, I just found that anyCollection, anyCollectionOf (clazz), anyList (Map, set), and anyListOf (clazz) are very interesting and user-friendly.
Public void login (String username, String password ){
If (username = null | username. length () = 0) return;
// Assume that we have certain requirements on the password strength and use a dedicated validator to verify the password's validity.
If (mPasswordValidator. verifyPassword (password) return; // <=
MUserManager. Logging mlogin (null, password );
}
// Create a mock object first
PasswordValidator mockValidator = Mockito. mock (PasswordValidator. class );
// If the mockValidator verifyPassword method is called and "xiaochuang_is_handsome" is passed in, true is returned.
Mockito. when (mockValidator. verifyPassword ("xiaochuang_is_handsome"). thenReturn (true );
// When the mockValidator verifyPassword method is called and "xiaochuang_is_not_handsome" is passed in, false is returned.
Mockito. when (validator. verifyPassword ("xiaochuang_is_not_handsome"). thenReturn (false );
Similarly, you can use the any series method to specify "xxx is returned regardless of any parameter value ":
// When the mockValidator verifyPassword method is called, true is returned, regardless of the Parameter
Mockito. when (validator. verifyPassword (anyString (). thenReturn (true );
2. We want to further test the code in NetworkCallback passed to mUserManager. Logs mlogin,
Mockito. doAnswer (new Answer (){
@ Override
Public Object answer (InvocationOnMock invocation) throws Throwable {
// Here we can obtain the parameter passed to the producer mlogin.
Object [] arguments = invocation. getArguments ();
// Callback is the third parameter.
NetworkCallback callback = (NetworkCallback) arguments [2];
Callback. onFailure (500, "Server error ");
Return 500;
}
}). When (mockUserManager). Invoke mlogin (anyString (), anyString (), any (NetworkCallback. class ));
// Assume that the implementation of the target class is like this.
Public class PasswordValidator {
Public boolean verifyPassword (String password ){
Return "xiaochuang_is_handsome". equals (password );
}
}
In addition, spy
@ Test
Public void testSpy (){
// It is similar to creating a mock, except that the spy method is called instead of the mock method. Spy usage
PasswordValidator spyValidator = Mockito. spy (PasswordValidator. class );
// By default, the spy object calls the real logic of this class and returns the corresponding return value.
SpyValidator. verifyPassword ("xiaochuang_is_handsome"); // true
SpyValidator. verifyPassword ("xiaochuang_is_not_handsome"); // false
// The spy object method can also specify specific behavior
Mockito. when (spyValidator. verifyPassword (anyString (). thenReturn (true );
// Similarly, the method call of the spy object can be verified.
SpyValidator. verifyPassword ("xiaochuang_is_handsome ");
Mockito. verify (spyValidator). verifyPassword ("xiaochuang_is_handsome"); // pass
}