Currently I'm using MockK library (version 1.8.1) for unit tests in Android Dev, and I the problem is I can't mock Patterns.EMAIL_ADDRESS.
Test cases throw NPE every time this property gets invoked.
I tried mockkStatic(Patterns::class), but #Before method crashes with NPE while applying the rule every { Patterns.EMAIL_ADDRESS.pattern() } returns EMAIL_REGEX_STRING.
Class I'm trying to test:
public class EmailValidator {
private static final String EMPTY = "";
private final Context context;
#Inject
public EmailValidator(Context context) {
this.context = context;
}
public String isValidEmail(String email) {
if (StringUtils.isEmpty(email)) {
return context.getString(R.string.sign_up_error_email_empty);
}
if (!email.matches(Patterns.EMAIL_ADDRESS.pattern())) {
return context.getString(R.string.sign_up_error_email_validate);
}
return EMPTY;
}}
Try using
PatternsCompat.EMAIL_ADDRESS.pattern()
instead of just
Patterns.EMAIL_ADDRESS.pattern()
that did the job for me.
Instead of using Patterns.EMAIL_ADDRESS directly, you could create a wrapper around it then mock or fake the wrapper.
The wrapper could be a method, like:
class EmailValidator {
fun isValidEmail(email: String) {
if (StringUtils.isEmpty(email)) {
return context.getString(R.string.sign_up_error_email_empty);
}
if (!email.matches(getEmailPattern())) {
return context.getString(R.string.sign_up_error_email_validate);
}
}
private fun getEmailPattern(): String = Patterns.EMAIL_ADDRESS.pattern()
}
and your test could mock it like:
#Test
fun `test email validator`() {
val validator = spyk(EmailValidator())
every { validator["getEmailPattern"]() } returns yourTestPattern
assertThat(validator.isValidEmail("blah blah blah")).isFalse()
}
Or create a class that wraps it, maybe a PatternFactory class
class PatternFactory {
fun getEmailPattern(): String = ...
fun getVinPattern(): String = ...
}
then pass in PatternFactory in as a dependency and mock it for the test
Related
How to use Mockito.mockStatic for mocking static methods in kotlin android ?
This is my code:
class MyUtilClassTest {
#Test
fun testIsEnabled() {
Mockito.mockStatic(MyUtilClass::class.java, Mockito.CALLS_REAL_METHODS)
.use { mocked ->
mocked.`when`<Boolean> { MyUtilClass.isEnabled() }.thenReturn(true)
assertTrue(MyUtilClass.isEnabled())
}
}
}
object MyUtilClass {
fun isEnabled(): Boolean = false
}
I am getting this exception:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
you stub either of: final/private/equals()/hashCode() methods.
Those methods cannot be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
inside when() you don't call method on mock but on some other object.
If you annotate your function isEnabled with #JvmStatic, you won't get any error. As #Neige pointed out, static functions in Kotlin are actually not static in bytecode by default. Therefore, we need to mark our function with #JvmStatic in order to generate additional static getter/setter methods.
object MyUtilClass {
#JvmStatic
fun isEnabled(): Boolean = false
}
From the JVM point of view MyUtilClass.isEnabled() is not a static class/function.
You can use Show Kotlin Bytecode to understand what is behind
public final class MyUtilClass {
public static final MyUtilClass INSTANCE;
public final boolean isEnabled() {
return false;
}
private MyUtilClass() {
}
static {
MyUtilClass var0 = new MyUtilClass();
INSTANCE = var0;
}
}
I am using Mockito for writing unit test case in Android. I am stuck into one method where I am modify Object and pass it to mocked method, Not able to understand how to write unit test case for this
Class LocationViewModel{
private LocationInteractor locationInteractor;
LocationViewModel (LocationInteractor locationInteractor){
this.locationInteractor =locationInteractor;
}
#Override
public Single<List<String>> getRecentLocations( LocationViewType locationViewType) {
return locationInteractor.getUpdatedRecentLocation(getRecentLocationFilter(locationViewType),locationViewType);
}
private Map<String, String[]> getRecentLocationFilter(LocationViewType locationViewType) {
LocationFilter locationfilter = new LocationFilter();
if (locationViewType == LocationViewType.DEFAULT_LOCATIONS) {
return locationFilter.getRecentDefaultLocationFilter();
} else if (locationViewType == SETTING_LOCATIONS) {
return locationFilter.getRecentSettingLocationFilter();
} else if (locationViewType == LocationViewType.INVENTORY_LOCATION) {
return locationFilter.getRecentSettingLocationFilter();
} else {
return locationFilter.getRecentCurrentLocationFilter();
}
}
}
Class LocationViewModelTest{
#Mock private LocationInteractorContract mockLocationInteractor;
private LocationViewModelContract locationViewModel;
#Before
public void setUp() {
initMocks(this);
locationViewModel = new LocationViewModel(mockLocationInteractor)
}
#Test
public void getRecentLocationsList_check_for_Null() {
when(mockLocationInteractor.getUpdatedRecentLocation(anyMap(),LocationViewType.SETTING_LOCATIONS)) ......Line 1
.thenReturn(Single.error(NullPointerException::new));
locationViewModel
.getRecentLocations(LocationViewType.SETTING_LOCATIONS)
.test()
.assertFailure(NullPointerException.class);
}
}
When I use anyMap() in Line no 1 it throws - org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
When I use new HashMap<>() in Line no 1 it throws NullPointerException
Want to write test case for method - getRecentLocations where getRecentLocationFilter is private method
For the InvalidUseOfMatchersException, the reason is probably that you have to use either all values or all matchers. For example:
when(mockLocationInteractor.getUpdatedRecentLocation(anyMap(), any())
In my current Android project I am investigating the use of Kotlin.
I am rewriting a 100% Java Android app to 100% Kotlin.
I'm stuck with attempting to implement my Java step builders though.
I employed Java step Builders as they force users of my code to supply all required data and/or functions before being able to execute an associated RxJava process.
These RxJava processes are complex and I wished to simplify their initialisation and execution as much as possible.
The use of Java Step builders allow developers to write the following code:-
Sequence.builder()
.stepOne(one)
.stepTwo(two)
.stepThree(three)
.build()
.execute();
What I am looking for is a Kotlin version of this approach.
My initial thought was that Kotlin would support Builders and Step Builders.
I am not "precious" about employing Builders in Kotlin, the Kotlin solution must force the developers that use my code to have supplied all required data and/or functions before they are able to execute the associated "executed" code.
From investigating Kotlin I've discovered internal DSLs which are sounding both interesting topic in themselves and a possible solution to this particular question.
I have a number of Step Builders to implement, none of these have more than 6 parameters. I do like to try and keep to SOLID no more than three parameters rule though.
Also if it makes any difference, some of the passed parameters are RxJava Actions and Consumers. Default values are not relevant here as none of the parameters have viable default values.
UPDATE
My Java step builders all resemble this:-
public class ExampleSequence extends Sequence {
private static final String TAG = "ExampleSequence";
private final Action onComplete;
private final Consumer<? super Throwable> onError;
/**
* #param builder
*/
private ExampleSequence(final Builder builder) {
super(builder.getDoLoginRefreshFail());
this.onError = builder.getOnError();
this.onComplete = builder.getOnComplete();
}
/**
*
*/
public static OnCompleteAction builder() {
return new Builder();
}
public interface OnCompleteAction {
onErrorAction onComplete(#NonNull final Action onComplete);
}
public interface onErrorAction {
DoLoginRefreshFail onError(#NonNull final Consumer<? super Throwable> onError);
}
public interface DoLoginRefreshFail {
Build doLoginRefreshFail(#NonNull final Action doLoginRefreshFail);
}
public interface Build {
ExampleSequence build();
}
#SuppressLint("CheckResult")
public void execute() {
final AtomicInteger retryCounter = new AtomicInteger(0);
final Observable<Response<GraphqlQueryResponse>> feedArticles = getPageAndNextInboxArticles(offset, limit)
.onErrorResumeNext(manufactureResumeNext())
.subscribeOn(Schedulers.io());
final Observable<Response<GraphqlQueryResponse>> readingListArticles = getPageAndReadingListArticles(readingListoffset, limit)
.onErrorResumeNext(manufactureResumeNext())
.subscribeOn(Schedulers.io());
login()
.flatMap(...)
.ignoreElement()
.andThen(...)
.andThen(...)
.ignoreElements()
.andThen(...)
.flattenAsObservable(x -> x)
.flatMapCompletable(...)
.retryWhen(errors -> errors.flatMap(e -> constructRetryHandler(retryCounter, e)))
.doOnComplete(onComplete)
.doOnError(onError)
.doAfterTerminate(doAfterTerminate())
.doOnSubscribe(compositeDisposable::add)
.blockingAwait();
}
/**********************************************************************************
*
* BUILDER
*
*/
public static class Builder implements OnCompleteAction, onErrorAction, DoLoginRefreshFail, Build {
private Action onComplete;
private Consumer<? super Throwable> onError;
private Action doLoginRefreshFail;
/***********************************************************************
*
*/
#Override
public ExampleSequence build() {
return new ExampleSequence(this);
}
#Override
public onErrorAction onComplete(#NonNull final Action onComplete) {
this.onComplete = onComplete;
return this;
}
#Override
public DoLoginRefreshFail onError(#NonNull final Consumer<? super Throwable> onError) {
this.onError = onError;
return this;
}
#Override
public Build doLoginRefreshFail(#NonNull final Action doLoginRefreshFail) {
this.doLoginRefreshFail = doLoginRefreshFail;
return this;
}
/**
* #return the onError
*/
Consumer<? super Throwable> getOnError() {
return onError;
}
/**
* #return the onComplete
*/
Action getOnComplete() {
return onComplete;
}
Action getDoLoginRefreshFail() {
return doLoginRefreshFail;
}
}
}
The step builder pattern in Kotlin is completely doable, and I've provided an example of it that mirrors the Java example you provided.
class ExampleSequence private constructor(builder: Builder): Sequence(builder.doLoginRefreshFail) { //This is your "super()" call.
//This is equivalent to assigning the final variables [onComplete] and [onError] in the class constructor
private val onComplete = builder.onComplete
private val onError = builder.onError
//More info about companion objects here: https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects
companion object {
//Java will see this as [ExampleSequence.Companion.builder()] unless you add this annotation
#JvmStatic
fun builder(): OnCompleteAction = Builder()
}
fun execute() {
//Do your stuff here...
}
//The following classes and interfaces are similar to being static inner classes. If you want the classes to access
//fields of the enclosing outer class, you must use the keyword [inner] before declaring the class. Example:
// inner class Foo { ... }
interface OnCompleteAction {
fun onComplete(onComplete: Action): onErrorAction
}
interface DoLoginRefreshFail {
fun doLoginRefreshFail(doLoginRefreshFail: Action): Build
}
interface onErrorAction {
fun onError(onError: Consumer<in Throwable>): DoLoginRefreshFail //The [in] keyword is the same as saying Consumer<? super Throwable>
}
interface Build {
fun build(): ExampleSequence
}
class Builder: OnCompleteAction, onErrorAction, DoLoginRefreshFail, Build {
//The [lateinit] keyword states that this variable will be initialized later. Calling it before it is initialized will throw an exception
lateinit var onComplete: Action
private set //Only this class can modify.
lateinit var onError: Consumer<in Throwable>
private set
lateinit var doLoginRefreshFail: Action
private set
//No special differences here... oooh, inlined [override] keyword!
override fun onComplete(onComplete: Action): onErrorAction {
this.onComplete = onComplete
return this
}
override fun doLoginRefreshFail(doLoginRefreshFail: Action): Build {
this.doLoginRefreshFail = doLoginRefreshFail
return this
}
override fun onError(onError: Consumer<in Throwable>): DoLoginRefreshFail {
this.onError = onError
return this
}
override fun build(): ExampleSequence = ExampleSequence(this)
//Where are the getter methods? If you look at the variable declarations, they are public by default.
//This means that these variables are public read, but can only be set by this class only. In other words, built-in getter!
}
}
However, in a pure Kotlin project, step builder is sort of an anti-pattern. With default and named parameters built into the language, you can actually achieve SOLID by a simple data class. Taking the ExampleSequence class for example, your solution could look something like:
data class ExampleSequence(
private val onComplete: Action,
private val onError: Consumer<in Throwable>,
private val doLoginRefreshFail: Action,
private val aNewParam: String = "Default")
: Sequence(doLoginRefreshFail) { //This is your "super()" call.
fun execute() {
//Do your stuff here...
}
}
fun foo() {
//Example of using named parameters and passing in variables. Notice parameters aren't in the same order as how it is declared in the class
ExampleSequence(
onError = Consumer(),
onComplete = Action(),
doLoginRefreshFail = Action()
).execute()
//Since I added [aNewParam], instead of using the default, let's change it.
ExampleSequence(
onError = Consumer(),
onComplete = Action(),
doLoginRefreshFail = Action(),
aNewParam = "Something else!"
).execute()
}
Here is a nice article going into a bit more detail: https://dev.to/chrisvasqm/avoiding-the-builder-design-pattern-in-kotlin-3b1a
Also, in case you need another example of a step builder pattern in Kotlin, you might want to check this out too: https://www.baeldung.com/kotlin-builder-pattern
I am facing a very weird issue here.
Following is my Test class:
SearchViewModel.java
#RunWith(PowerMockRunner.class)
#PrepareForTest({JSONReader.class, ConstantsPath.class, DatabaseManager.class})
public class SearchViewModelTest {
#Rule
public TestRule rule = new InstantTaskExecutorRule();
private String indexSearchContent;
private String fullTextSearchContentGL1, fullTextSearchContentGL2, fullTextSearchContentGL3, fullTextSearchContentGL4;
private String searchQuery = "a";
private List<FullTextSearchItem> fullTextSearchResult;
private String behaviorString;
private SearchViewModel searchViewModel;
private DatabaseManager databaseManager;
private void initInputs() throws IOException {
indexSearchContent = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getIndexSearchFilePath()));
behaviorString = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getBehavioralFilePath()));
fullTextSearchContentGL1 = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getFullTextSearchFilePath("1")));
fullTextSearchContentGL2 = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getFullTextSearchFilePath("2")));
fullTextSearchContentGL3 = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getFullTextSearchFilePath("3")));
}
private void mockDaggerDependency() {
AppInfo appInfo = Mockito.mock(AppInfo.class);
Mockito.when(appInfo.getAppName()).thenReturn("testApp");
Mockito.when(appInfo.getAppLanguage()).thenReturn("EN");
TestApplicationModule module = new TestApplicationModule(appInfo);
DatabaseModule databaseModule = Mockito.mock(DatabaseModule.class);
Component component = DaggerComponent.builder().applicationModule(module).databaseModule(databaseModule).build();
MyApplication.setComponent(component);
}
private void mockGuidelineList() throws Exception {
databaseManager = PowerMockito.mock(DatabaseManager.class);
List<Guideline> mockedGls = new ArrayList<>();
Guideline gl = new Guideline();
gl.setGuidelineId("1");
mockedGls.add(gl);
gl = new Guideline();
gl.setGuidelineId("2");
mockedGls.add(gl);
gl = new Guideline();
gl.setGuidelineId("3");
mockedGls.add(gl);
Mockito.when(databaseManager.getGuidelinesListByPositionOnHome()).thenReturn(mockedGls);
PowerMockito.whenNew(DatabaseManager.class).withNoArguments().thenReturn(databaseManager);
// prepare expected output for fulltext search
Observable.fromIterable(new DatabaseManager().getGuidelinesListByPositionOnHome())
.map(Guideline::getGuidelineId)
.flatMap(glId -> BehavioralFile.<List<FullTextSearchItem>>loadJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath(glId),
new TypeToken<List<FullTextSearchItem>>() {
}.getType()).toObservable()
.flatMapIterable(fullTextSearchitems -> fullTextSearchitems)
.filter(item -> item.getText().toLowerCase().contains(searchQuery.toLowerCase()))).<List<FullTextSearchItem>>toList()
.subscribe(list -> {
fullTextSearchResult = list;
});
}
#Before
public void setUp() throws Exception {
MainActivityTest.overrideRxJavaPlugins();
mockDaggerDependency();
initInputs();
PowerMockito.mockStatic(JSONReader.class);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getIndexSearchFilePath())).willReturn(indexSearchContent);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath("1"))).willReturn(fullTextSearchContentGL1);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath("2"))).willReturn(fullTextSearchContentGL2);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath("3"))).willReturn(fullTextSearchContentGL3);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getBehavioralFilePath())).willReturn(behaviorString);
mockGuidelineList();
searchViewModel = new SearchViewModel();
}
#After
public void tearDown() throws Exception {
}
#Test
public void loadFullTextSearch() throws Exception {
//searchViewModel.loadFullTextSearch_(searchQuery);
loadFullTextSearch(searchQuery);
assertEquals(searchViewModel.fullTextSearchListLiveData.getValue().size(), fullTextSearchResult.size());
}
private void loadFullTextSearch(String query) {
// following line is throwing exception if put in another class.
Observable.fromIterable(new DatabaseManager().getGuidelinesListByPositionOnHome())
.map(Guideline::getGuidelineId)
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.flatMap(glId -> BehavioralFile.<List<FullTextSearchItem>>loadJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath(glId),
new TypeToken<List<FullTextSearchItem>>() {
}.getType()).toObservable()
.flatMapIterable(fullTextSearchitems -> fullTextSearchitems)
.filter(item -> item.getText().toLowerCase().contains(query.toLowerCase()))).<List<FullTextSearchItem>>toList().toObservable()
.subscribe(list -> searchViewModel.fullTextSearchListLiveData.setValue(list));
}
}
here loadFullTextSearch() test cases works perfectly fine until i remove comment of line searchViewModel.loadFullTextSearch_(searchQuery);,
check modified test case:
#Test
public void loadFullTextSearch() throws Exception {
searchViewModel.loadFullTextSearch_(searchQuery);
//loadFullTextSearch(searchQuery);
assertEquals(searchViewModel.fullTextSearchListLiveData.getValue().size(), fullTextSearchResult.size());
}
Here comes the weird part: both the functions(earchViewModel.loadFullTextSearch_(), loadFullTextSearch()) has same code but loadFullTestSearch_() is in SearchViewModel class and loadFullTextSearch() in is test cases it self, that i did to figure out why constructor of DatabaseManager class is not getting mocked(Observable.fromIterable(new DatabaseManager().getGuidelinesListByPositionOnHome())) when code is in SearchViewModel class.
Note: I am mocking constructor of DatabaseManager class. check mockGuidelineList() method. Mocked method is working if constructor is getting invoked in same test class.
Exception i get is :
java.lang.NullPointerException: Cannot return null from a non-#Nullable #Provides method
Because i am using dagger and the constructor i am mocking initialises database object dependency.
public DatabaseManager() {
MyApplication.getComponent().inject(this);
}
Any help would be appreciated, Thanks.
I was doing everything fine but missed to add class where constructor is being invoked in #PrepareForTest annotation.
So in my case this has to be:
#PrepareForTest({JSONReader.class, ConstantsPath.class, DatabaseManager.class, SearchViewModel.class})
this stackoverflow answer helped me out.
I am trying to do an unit test for an android app and I need to get a string from res.string resources. The class that I want to test is a POJO class. I am doing the app in two languages, due to this, I need to get a string from resource. The problem is that I cannot get the context or the activity, is possible? I know that with Instrumentation test I can do it, but I need to test some functions (white box test) before to do the instrumentation test (black box test).
This is the function that I have to test:
public void setDiaByText(String textView) {
getll_diaSeleccionado().clear();
if (textView.contains(context.getResources().getString(R.string.sInicialLunes))) {
getll_diaSeleccionado().add(0);
getIsSelectedArray()[0] = true;
getI_idiaSeleccionado()[0] =1;
} else
{
getIsSelectedArray()[0] = false;
getI_idiaSeleccionado()[0] =0;
}
}
And this is the test:
#Test
public void setDiaByTextView() {
String texto = "L,M,X,J,V,S,D";
alertaPOJO.setDiaByText(texto);
assertEquals(alertaPOJO.getIsSelectedArray()[0], true);
assertEquals(alertaPOJO.getI_idiaSeleccionado()[0], 1);
}
It crash when try to do context.getResources().getString(R.string.sInicialLunes))
If I put 'Mon' instead of context.getResources().getString(R.string.sInicialLunes)) or 'L' it work perfectly so, is possible to get the context or the activity in order to access to resource folder?
I am testing with Mockito and the setUp function is:
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = Mockito.mock(Alerta.class);
Mockito.when(mContext.getApplicationContext()).thenReturn(mContext);
alertaPOJO = new AlertaPOJO();
}
Thanks
If you are using Context only for obtaining String resource, I would go by mocking only getResources().getString() part like this (see JUnit4 notation):
#RunWith(MockitoJUnitRunner.class)
public class AlertaPOJOTest {
#Mock
Context mMockContext;
#Test
public void setDiaByTextView() {
String texto = "L,M,X,J,V,S,D";
when(mMockContext.getString(R.string.sInicialLunes))
.thenReturn(INITIAL_LUNES);
alertaPOJO.setDiaByText(texto);
assertEquals(alertaPOJO.getIsSelectedArray()[0], true);
assertEquals(alertaPOJO.getI_idiaSeleccionado()[0], 1);
}
}
There are many reasons to stay with JVM tests, most important one, they are running quicker.
Untested: would it work to use the below, and probably targetContext?
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
You don't have a real android Context while you are using JVM unit test. For your case, maybe you can try Android Instrumentation Test, typically it is implemented in the "androidTest" directory of your project.
If you use MockK it's the same.
#RunWith(AndroidJUnit4::class)
class YourClassUnitTest : TestCase() {
#MockK
private lateinit var resources: Resources
#Before
public override fun setUp() {
MockKAnnotations.init(this)
}
#Test
fun test() {
every {
resources.getQuantityString(R.plurals.age, YEARS, YEARS)
} returns AGE
every {
resources.getString(
R.string.surname,
SURNAME
)
} returns TITLE
// Assume you test this method that returns data class
// (fields are calculated with getQuantityString and getString)
val data = getData(YEARS, SURNAME)
assertEquals(AGE, data.age)
assertEquals(TITLE, data.title)
}
companion object {
const val YEARS = 10
const val AGE = "$YEARS years"
const val SURNAME = "Johns"
const val TITLE = "Mr. $SURNAME"
}
}
See also Skip a parameter in MockK unit test, Kotlin to get a result of string resources for any data.