Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes: #3343 TextUtils.isEmpty creates problems when unit testing with Mockito #3344

Merged
merged 3 commits into from
Jan 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions app/src/test/java/android/text/TextUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package android.text;


import androidx.annotation.Nullable;

/**
* This Class Mocks TextUtils for the purpose of testing.
* NOTE: This class would not change the function of the TextUtils used in app
* it onlt mocks it for the unit tests
*
*/
public class TextUtils {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kbhardwaj123 Where is this class getting used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In short, take any piece of code containing TextUtils.isEmpty() it will always return false even if you pass null, you can see that in the screenshot above, this class mocks that and gives perfect result again refer to second screenshot above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered this while i was unit testing on CategoryModel in other PR (which is also ready for you to review :) )

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't understand, where is this class used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It goes like this:
Mockito is not capable of mocking TextUtils.isEmpty

So inside a unit test TextUtils.isEmpty(null) returns false which is Wrong!
See the first screenshot I posted above,
This Class mocks the TextUtils class Correctly, please refer to my second screenshot
So This Class will be used by every unit test which tries to test a piece of code which contains TextUtils.isEmpty

Copy link
Contributor Author

@kbhardwaj123 kbhardwaj123 Jan 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@kbhardwaj123 kbhardwaj123 Jan 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The startUpload() inside UploadControllerTest.kt tests uploadController.startUpload at line 119 in UploadController.java, that's one of the instances where this class will be used

/**
* mocks TextUtils.isEmpty
*/
public static boolean isEmpty(@Nullable CharSequence str) {
return str == null || str.length() == 0;
}

/**
* mocks TextUtils.equals
*/
public static boolean equals(CharSequence a, CharSequence b) {
if (a == b) return true;
int length;
if (a != null && b != null && (length = a.length()) == b.length()) {
if (a instanceof String && b instanceof String) {
return a.equals(b);
} else {
for (int i = 0; i < length; i++) {
if (a.charAt(i) != b.charAt(i)) return false;
}
return true;
}
}
return false;
}

/**
* mocks TextUtils.isDigitsOnly
*/
public static boolean isDigitsOnly(CharSequence str) {
final int len = str.length();
for (int cp, i = 0; i < len; i += Character.charCount(cp)) {
cp = Character.codePointAt(str, i);
if (!Character.isDigit(cp)) {
return false;
}
}
return true;
}

/**
* mocks TextUtils.isNewline
*/
private static boolean isNewline(int codePoint) {
int type = Character.getType(codePoint);
return type == Character.PARAGRAPH_SEPARATOR || type == Character.LINE_SEPARATOR
|| codePoint == 10;
}

/**
* Returns whether the given CharSequence contains any printable characters.
*/
public static boolean isGraphic(CharSequence str) {
final int len = str.length();
for (int cp, i=0; i<len; i+=Character.charCount(cp)) {
cp = Character.codePointAt(str, i);
int gc = Character.getType(cp);
if (gc != Character.CONTROL
&& gc != Character.FORMAT
&& gc != Character.SURROGATE
&& gc != Character.UNASSIGNED
&& gc != Character.LINE_SEPARATOR
&& gc != Character.PARAGRAPH_SEPARATOR
&& gc != Character.SPACE_SEPARATOR) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class UploadControllerTest {
@Test
fun startUpload() {
val contribution = mock(Contribution::class.java)
`when`(contribution.getCreator()).thenReturn("Creator")
uploadController!!.startUpload(contribution)
}
}