简体   繁体   中英

How to mock views for unit testing in android

I have a helper class that I am using for TextInputEditText field validation in my application. It takes in an array of TextInputEditText with different tags. Firstly it sieve anyone that is empty and then proceed to validate them based on their different tag. I want to be able to test the class and pass array of TextInputEditText with tags as a parameter but finding it hard to mock an TextInputEditText.

class Validation private constructor(
    var respond:TextInputEditText,
    vararg edits: TextInputEditText
) {

    class Builder(
        var email: TextInputEditText? = null,
        var password: TextInputEditText? = null,
        var phoneNumber: TextInputEditText? = null,
        var respond:TextInputEditText?=null,
        vararg var edits: TextInputEditText

    ) {

        fun getEmptyField(edits: Array<out TextInputEditText>): Builder = apply {
            this.edits = edits
            for (edit in edits) {
                when {
                    edit.text?.isEmpty() == true -> {
                        edit.error = "${edit.tag} is required"
                        this.respond = edit
                        return@apply
                    }
                    edit.tag.toString().contains("email", true) -> {
                        this.email = edit
                    }
                    edit.tag.toString().contains("password", true) -> {
                        this.password = edit
                    }
                    edit.tag.toString().contains("phone", true) -> {
                        this.phoneNumber = edit
                    }
                }

            }
        }
        fun email() = apply {
            val emailPattern = Regex("""^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*${'$'}""")
            val matchedEmail = emailPattern.matches(this.email?.text.toString())
            if(matchedEmail){
                return@apply
            }
            else{
                this.respond = email
                this.respond?.error = "Invalid"
                return@apply
            }
        }
        fun password() = apply {
            val passwordPattern = Regex("""^[a-zA-Z0-9@$!.%*#?&]{6,}$""")
            val matchedPassword = passwordPattern.matches(this.password?.text.toString())
            if(matchedPassword){
                return@apply
            }
            else{
                this.respond = password
                this.respond?.error = "Invalid"
                return@apply
            }
        }
        fun phone() = apply {
            val phonePattern = Regex("""^(80|70|90|81)([12356709])\d{7}$""")
            val matchedPhone = phonePattern.matches(this.phoneNumber.toString())
            if(matchedPhone){
                return@apply
            }
            else{
                this.respond = phoneNumber
                this.respond?.error = "Invalid"
                return@apply
            }

        }
        fun build():Validation? {
            val listOfDefaulters = arrayListOf<TextInputEditText>()
            for (edit in this.edits){
                if (edit.error != null){
                    listOfDefaulters.add(edit)
                    this.respond = listOfDefaulters[0]
                    this.respond!!.error = "Invalid"
                }
            }
           return respond?.let { Validation(it, *edits) }
        }
    }

}

How can I test this class and pass the stub.

I finally found a work around. This might help someone else. You can find the code below.

Basically what I did was to pass in a pair with custom class to simulate the edit-text and corresponding optional edit text. With that I was able to test the class with only the custom class.

/**
 * @author Abdulrasaq Durosomo
 * @param respond
 * @param edits
 */
class Validation private constructor(
    var respond: Pair<CustomEditTextField, TextInputEditText?>,
    vararg var edits: Pair<CustomEditTextField, TextInputEditText?>
) {

    class Builder(
        var emailPair: Pair<CustomEditTextField, TextInputEditText?>? = null,
        var passwordPair: Pair<CustomEditTextField, TextInputEditText?>? = null,
        var phoneNumberPair: Pair<CustomEditTextField, TextInputEditText?>? = null,
        var respond: Pair<CustomEditTextField, TextInputEditText?>? = null,
        vararg var fieldPairList: Pair<CustomEditTextField, TextInputEditText?>

    ) {

        /**
         * @param edits
         * This separates field based on their tag and also rejects empty field
         */
        fun separateFieldByTag(edits: List<Pair<CustomEditTextField, TextInputEditText?>>): Builder = apply {
            this.fieldPairList = edits.toTypedArray()
            for (edit in edits) {
                when {
                    edit.first.text.isEmpty() -> {
                        edit.first.error = "${edit.first.tag} is required"
                        edit.second?.error = "${edit.first.tag} is required"
                        this.respond = edit
                        return@apply
                    }
                    edit.first.tag.toString().contains("email", true) -> {
                        this.emailPair = edit
                    }
                    edit.first.tag.toString().contains("password", true) -> {
                        this.passwordPair = edit
                    }
                    edit.first.tag.toString().contains("phone", true) -> {
                        this.phoneNumberPair = edit
                    }
                }
            }
        }

        /**
         * Validate email address
         */
        fun email() = apply {
            val emailPattern = Regex("""^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*${'$'}""")
            val matchedEmail = emailPattern.matches(this.emailPair?.first?.text.toString())
            if (matchedEmail) {
                return@apply
            } else {
                this.respond = emailPair
                this.respond?.first?.error = "Invalid"
                this.respond?.second?.error = "Invalid"
                return@apply
            }
        }

        /**
         * Validate password
         */
        fun password() = apply {
            val passwordPattern = Regex("""^[a-zA-Z0-9@$!.%*#?&]{6,15}$""")
            val matchedPassword = passwordPattern.matches(this.passwordPair?.first?.text.toString())
            if (matchedPassword) {
                return@apply
            } else {
                this.respond = passwordPair
                this.respond?.first?.error = "Invalid"
                this.respond?.second?.error = "Invalid"
                return@apply
            }
        }

        /**
         * Validate phone number
         */
        fun phone() = apply {
            val phonePattern = Regex("""^(80|70|90|81)([12356709])\d{7}$""")
            val matchedPhone = phonePattern.matches(this.phoneNumberPair?.first?.text.toString())
            if (matchedPhone) {
                return@apply
            } else {
                this.respond = phoneNumberPair
                this.respond?.first?.error = "Invalid"
                this.respond?.second?.error = "Invalid"
                return@apply
            }
        }

        /**
         * Build validation
         */
        fun build(): Validation? {
            val listOfDefaulters = arrayListOf<Pair<CustomEditTextField, TextInputEditText?>?>()
            for (edit in this.fieldPairList) {
                if (edit.first.error != "") {
                    listOfDefaulters.add(edit)
                    this.respond = listOfDefaulters[0]
                    this.respond!!.second?.error = "Invalid"
                }
            }
            return respond?.let { Validation(it, *fieldPairList) }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM