El Arsenal de Android: herramientas de prueba

Artículos promedio

Consulte este artículo para obtener más información sobre esta biblioteca:

¿Por qué mapache?

Ha habido varias formas de burlarse de la respuesta de una llamada a la API. Tenemos muchos buenos marcos para este propósito. Pero, ¿qué pasa si necesitamos devolver una respuesta ficticia basada en la solicitud y sus parámetros? De esto se trata esta biblioteca. Raccoon es un complemento de escuchas telefónicas que ayudará al desarrollador a simular una respuesta basada en la solicitud. La biblioteca utiliza la API de Reflection bajo el capó para hacer todo el proceso.

Perspectivas

La integración de esta biblioteca es tan compacta que el desarrollador no tiene que dedicar mucho tiempo al proceso. Básicamente necesitamos hacer 3 adiciones principales:

  • Agregue el complemento Interceptor
  • Agregue la clase de servicio en el directorio AndroidTest
  • Agregue la clase Controller y la definición de punto final al directorio AndroidTest.

Gradle

Agregue lo siguiente al archivo root build.gradle.kts de su proyecto

allprojects {
  repositories {
 maven ("https://jitpack.io")
  }
}

Agregue lo siguiente al archivo build.gradle.kts de su proyecto

dependencies {
  
  // Other dependencies
  implementation("com.github.iamjosephmj:Raccoon:1.0.7")
     
}

Uso basico

Add interceptor plugin

Retrofit

Los usuarios de la modernización deben agregar el RaccoonOkHttpPlugin como el interceptor

  val okHttpClient = OkHttpClient.Builder()
            .addInterceptor(RaccoonOkHttpPlugin())
            .build()

  val retrofit = Retrofit.Builder()
            .client(okHttpClient)
            .build()

Agregar este complemento al proyecto real no está de más hasta que RaccoonStub la clase se inicializa.

Add Controller Class

Esta es una de las clases principales que está estudiando la biblioteca de Raccoon. ¿Está la clase de controlador donde estaban? Endpoint se hacen las definiciones. Los desarrolladores pueden mantener la lógica relacionada Endpoints en el mismo Controller

@ControllerModule
class MockController : RaccoonController() {

    override fun setup() {
        // Do the DI related stuff
    }

    @RaccoonEndpoint(
        endpoint = "your endpoint",
        responseTime = 100, /* delay in api response delivery */
        RaccoonRequestType.GET /* user can define their request types here */
    )
    fun fetchToDoList(@Params headers: Parameters): RaccoonResponse {
        return </* Your response object */>
        .buildRaccoonResponse(statusCode = 200 /* STATUS code of the api response */)
    }


    override fun tearDown() {
        // clean up memory.
    }
}

setUp()

Si el usuario desea importar algunos objetos vía DI, esta función será el punto de entrada para hacer lo mismo. Esta función se llama antes de que se llame a la definición de punto final.

tearDown()

Esta función es la mejor candidata para liberar memoria después de realizar la definición del punto final. Esta función se llama después de que se haya llamado a la definición del punto final.

Endpoint Definition function

El usuario puede definir cualquier nombre para la función de definición de punto final. El único requisito que tiene la biblioteca es que el usuario dé una @RaccoonEndpoint por lo mismo. Tome el ejemplo anterior para ver la anotación en acción.

La función de definición de punto final tiene un tipo de retorno RaccoonResponse. El desarrollador puede crear directamente RaccoonResponse objeto con

    RaccoonResponse(
        statusCode=200,
        body =/* json string */ "{ ... }"
    )

o pueden usar los objetos pojo compatibles con Moshi / Gson. Mapache proporciona una función de extensión auxiliar buildRaccoonResponse hacer lo mismo

 return </* Your response object */>
        .buildRaccoonResponse(statusCode = 200 /* STATUS code of the api response */)

También puede incluir varios controladores en una sola clase de controlador para mantener la modularidad en su diseño.

@ControllerModule(includeControllers = [MockController2::class /* you can add any number of controllers here */])
class MockController : RaccoonController() {

    // your implementation ...
}

Eche un vistazo al androidTest implementación para obtener más información sobre el mismo.

Add Service Class

La clase de servicio ayuda a la biblioteca a desarrollar una comprensión general de cómo escanear de manera eficiente los controladores para recuperar el punto final.

@RaccoonService
class MockService : RaccoonServiceImpl() {

    @RaccoonController
    fun providesMockController() = MockController::class
}

Este desarrollador debería:

  • Extender el RaccoonServiceImpl clase
  • Agregar @RaccoonService como una anotación para la clase de servicio.
  • Agregar @RaccoonController como una anotación para la función de proveedor de la clase de controlador ficticia.

Test class implementation

@RunWith(AndroidJUnit4::class)
class MainActivityTest {

    @Before
    fun setup() {
       // setup
        RaccoonStub.setUp(
                  RaccoonConfig.Builder()
                      .addService(MockService::class)
                      .addService(MockService2::class)
                      .addService(MockService3::class)
                      .setParserType(GsonPlugin())
                      .build()
              )
        /*
         * The developer can also use {@see MoshiPlugin} as the parserType as per the project
         * requirements
         */
    }

    /**
     * You should not launch the activity before the RaccoonStub initialization.
     * There can be scenarios where the app calls the API on launch. In such cases only launch the
     * Activity inside the test function
     */
    @get:Rule
    val rule = ActivityTestRule(
        MainActivity::class.java, false, false
    )

    @Test
    fun useAppContext() {
        // run your test
    }

    @After
    fun tearDown() {
       // cleans up the memory.
        RaccoonStub.teatDown()
    }

}

Raccoon TestRule

Puede definir testRule así:

 
// Seup raccoon stub
val raccoonTestRule = RaccoonTestRule {
     RaccoonStub.setUp(
      RaccoonConfig.Builder()
         .addService(ServiceClass::class)
                .build()
 )
}
 
// Setup activity testRule 
private val activityTestRule = ActivityTestRule(MainActivity::class.java)

@get:Rule
val chain: RuleChain = RuleChain
 /*
  * Always give raccoon testrule before the activity testRule, because this can be helpfull
  * if you app does an API call at the launch of an activity.
         */
 .outerRule(raccoonTestRule)
        .around(activityTestRule)
    

Contribución, problemas o ideas futuras

Si parte de Raccoon no funciona correctamente, asegúrese de informar un problema con Github. En el problema, proporcione tantos detalles como sea posible. Esto podría incluir código de muestra o los pasos exactos que siguió para que todos puedan reproducir el problema. Los proyectos de muestra son siempre la mejor manera :). ¡Esto hace que sea fácil para nuestros desarrolladores o alguien de la comunidad de código abierto comenzar!

Si tiene una idea para una función, envíe un problema con una solicitud de función o envíe una solicitud de extracción y trabajaremos con usted para fusionarla.

Pautas de contribución

¡Las contribuciones son más que bienvenidas!

  • Debe asegurarse de que todas las pruebas funcionen correctamente.
  • Debes recopilar un PR para desarrollar la sucursal.
  • Antes de aumentar un PR, asegúrese de que su código no haya tenido un problema con Android Studio Lint Analyzer.

Comparta y destaque el repositorio para mantenerme motivado.

.

Compruebe también

en vivo desde Droidcon, incluida la mayor actualización de Gemini en Android Studio y más lanzamientos del SDK de Android.

Acabamos de lanzar nuestro episodio de otoño de #TheAndroidShow en YouTube etcétera desarrollador.android.comy esta vez …

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *