Mocking un campo inyectado en las pruebas unitarias

Tengo una clase Presenter que utiliza un campo inyectado a través de Dagger, se ve algo así:

 public class RssListPresenter { @Inject RssService rssService; // <-- injected field public RssListPresenter() { setupDI(); } private void setupDI() { DaggerNetworkComponent.builder() .networkModule(new NetworkModule()) .build() .inject(this); } public void loadItems() { Rss rss = rssService.getRssFeed() // .... } } 

Todo funciona bien. Ahora, me gustaría probar la clase RssListPresenter . La pregunta es ¿cómo puedo proporcionar un RssService simulado al presentador?

Ofcourse puedo agregar un nuevo método setRssService(RssService rssService) al presentador y utilizarlo para proporcionar el simulacro de pruebas de unidad, pero agregar este método sólo para las pruebas de unidad no se siente bien. ¿Cuál sería la manera correcta de manejar esto?

Para mayor completitud aquí están las declaraciones de módulos y componentes:

 @Singleton @Component(modules = NetworkModule.class) public interface NetworkComponent { void inject(RssListPresenter presenter); } @Module public class NetworkModule { @Provides Retrofit provideRetrofit() { // ... } @Provides @Singleton RssService providePcWorldRssService(Retrofit retrofit) { return retrofit.create(RssService.class); } } 

Inyección de propiedad es como que no es tan fácil de probar. En este caso, la inyección Constructor es mucho mejor. Refactorice su constructor para que se vea así:

 private final RssService rssService; @Inject public RssListPresenter(RssService rssService) { this.rssService = rssService; } 

Ahora puedes probarlo fácilmente:

 //mocks RssService mockRssService; //system under test RssListPresenter rssListPresenter; @Before public void setup() { mockRssService = Mockito.mock(RssService.class); rssListPresenter = new RssListPresenter(mockRssService); } 

Probablemente no debería estar usando DaggerNetworkComponent.inject(this) dentro de RssListPresenter . En su lugar, debe configurar la daga para que al inyectar miembros en sus clases de nivel superior ( Activity , Fragment , Service ), pueda acceder al gráfico de objetos y crear una instancia de su RssPresenter .

¿Por qué sólo poner inyectores en la Activity y el Service y no en algo como RssListPresenter ? Estas son clases que son instanciadas por el sistema Android y por lo que no tiene más remedio que usar inyectores.

Para aclarar, Activity , Fragment , etc. son objetivos de inyección ideales. RssListPresenter etc se inyectan dependencias . Es necesario configurar el marco de inyección de dependencia, dagger, para que pueda proporcionar las dependencias correctas para inyectar en los objetivos de inyección.

Así que también necesitará escribir un método RssListPresenter para RssListPresenter

 @Provides provideRssListPresenter(RssService rssService) { return new RssListPresenteR(rssService); } 

Su clase viola algunos de los principios de SOLID , y esto hace que sea muy difícil para la unidad de prueba. Por supuesto, su clase viola el SRP (Single Responsability Principle) ya que tiene más de una razón para cambiar. También existe una posible violación de Inversión de Dependencia.

Recomiendo repensar el modelo de las clases, para que cada una de ellas desempeñe una función específica, y tenga una razón para cambiar.

  • Unidad Método de prueba que no contiene lambda expresión Android Studio
  • Adaptador RecyclerView en la prueba de unidad
  • Pruebas de unidad en Android Studio 0.8
  • Ejecutar pruebas de unidad en Guardar con Android Studio
  • AsyncTask onPostExecute () no se llama en caso de prueba de unidad
  • Cómo probar la unidad android y burlarse de un método estático
  • Prueba de unidad en la función de extensión de Kotlin en las clases de SDK de Android
  • ¿Cómo / Debo probar eventos de EventBus con Mockito?
  • Obtención de contexto en AndroidTestCase o InstrumentationTestCase en la función Prueba de unidad de Android Studio
  • Valor de Stub de Build.VERSION.SDK_INT en la prueba de unidad local
  • ¿Cómo puedo crear pruebas en Android Studio?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.