Como podemos acessar o contexto de uma aplicação no Robolectric?

112

Na verdade, preciso obter uma resposta de uma chamada de API, para isso eu solicitei Context.

user1667968
fonte

Respostas:

218

Atualizar.

Basta usar para as versões 1.xe 2.x:

Robolectric.application;

E para a versão 3.x:

RuntimeEnvironment.application;

E para a versão 4.x:

  • adicione ao seu build.gradlearquivo:

    testImplementation 'androidx.test:core:1.0.0'
    
  • recupere o contexto com:

    ApplicationProvider.getApplicationContext()
    
Eugen Martynov
fonte
11
Você colocou @RunWith (RobolectricTestRunner.class) para seus testes?
Eugen Martynov
4
Sim .. Eu adicionei ... mas ainda assim ele retorna nulo
user1667968
1
Eu fiz tudo o que você mencionou e ainda fico nulo. Posso estar faltando mais alguma coisa?
Moises Jimenez
13
Certifique-se também de não usar RuntimeEnvironment.applicationcódigo estático (como métodos anotados com @BeforeClass), pois o Robolectric provavelmente não será inicializado nesse ponto e o valor será null.
sfera
1
Além disso, isso faz com que o aplicativo vaze entre os testes .. o que pode não ser desejável
Chris
26

Você pode usar

RuntimeEnvironment.application
rds
fonte
4
no RoboElectric 3.0, Roboelectric.application não existe mais, então esta é provavelmente a melhor resposta
kenyee
19

Usa isto:

Robolectric.application
Xian
fonte
16

Adicionar

testImplementation "androidx.test:core-ktx:${deps.testrunner}"

E use:

private val app = ApplicationProvider.getApplicationContext()
John
fonte
import androidx.test.core.app.ApplicationProvider
luckyhandler
val appContext = ApplicationProvider.getApplicationContext <Context> ()
luckyhandler
2
Esta é a resposta correta com o Robolectric mais recente. Outros métodos mencionados aqui foram descontinuados ou removidos.
Gabor de
7

Para o mais recente Robolectric 4.3 a partir de agora em 2019 `

ShadowApplication.getInstance ()

`e

Roboletric.application

são ambos depreciados. Então estou usando

Context context = RuntimeEnvironment.systemContext;

para obter o contexto.

The_Martian
fonte
5

Para obter o contexto do aplicativo, você deve fazer o seguinte:

  1. annotate @RunWith (RobolectricTestRunner.class)
  2. RuntimeEnvironment.application.getApplicationContext ()
user1390616
fonte
2

Isso funciona para mim com Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext

Farrukh Najmi
fonte
Observe que parece que a versão 4.0 removerá esse método; melhor ficar com RuntimeEnvironment.applicationou RuntimeEnvironment.application.getApplicationContext()se estiver funcionando para você.
qix
2

A partir do lançamento 4.0-alpha-3 em 21 de julho, eles foram removidos ShadowApplication.getApplicationContext() . Fique com RuntimeEnvironment.application.getApplicationContext()para quaisquer testes anotados com @RunWith(RobolectricTestRunner::class).

Como um aparte, seu guia atual tem um exemplo de como obter recursos de string usando:

final Context context = RuntimeEnvironment.application;

(Observe que os javadocs para RuntimeEnvironmente ShadowApplicationatualmente refletem a versão não alfa 3.x.)

qix
fonte
2

Primeiro adicione o seguinte ao seu build.gradle:

testImplementation 'androidx.test:core:1.2.0'

então use:

ApplicationProvider.getApplicationContext() as Application

dougie
fonte
2

Em alguns casos, você pode precisar do contexto do seu aplicativo em vez do contexto padrão do Robolectris. Por exemplo, se você deseja obter o nome do seu pacote. Por padrão, o Robolectric retornará o org.robolectric.defaultnome do seu pacote. Para obter o nome real do seu pacote, faça o seguinte:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

Sua aula de teste:

@RunWith(RobolectricTestRunner.class)
@Config( manifest="AndroidManifest.xml")
public class FooTest {

@Test
public void fooTestWithPackageName(){
    Context context = ApplicationProvider.getApplicationContext();
    System.out.println("My Real Package Name: " + context.getPackageName());
}

}

Certifique-se de que em seu diretório de trabalho Run / Debug Configurations está definido como: $ MODULE_DIR $ insira a descrição da imagem aqui insira a descrição da imagem aqui

Kirill Karmazin
fonte
1

É mais seguro usar em Robolectric.getShadowApplication()vez de usar Robolectric.applicationdiretamente.

drspaceboo
fonte
Mas e se eu precisar acessar algumas propriedades personalizadas de meu aplicativo personalizado? Parece que não consigo obter o objeto real do aplicativo de sombra.
Denis Kniazhev
@DenisKniazhev Desculpe, não posso responder isso para você. Pouco depois de começarmos a usar o Robolectric, começamos a usar o Travis como nosso CI, e eles não funcionam bem. Meu palpite é que você pode lançá-lo em seu aplicativo ou pode precisar fazer um runner personalizado para ter acesso a ele dessa forma.
Boa
Obrigado, por enquanto, acabei de me limitar aRobolectric.application
Denis Kniazhev
6
Robolectric.getShadowApplication () não está disponível
IgorGanapolsky 01 de
1

Concordo com as respostas de @EugenMartynov e @rds ....

Um exemplo rápido pode ser encontrado em Volley-Marshmallow-Release

em NetworkImageViewTest.java

// mNIV = new NetworkImageView(Robolectric.application); mNIV = new NetworkImageView(RuntimeEnvironment.application);

O link do Volley está disponível em https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

você precisa adicionar dependências no módulo de volley no android studio como:

dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' testCompile 'org.robolectric:robolectric:3.1.2' }

Bhuro
fonte
1

No seu caso, acho que você deve estar ciente do que está realmente testando. Às vezes encontrando problemas de não testável código ou código aparentemente não testável é um sinal de que talvez seu código precise ser refatorado.

Para uma resposta de chamada de API, você pode não querer testar a própria chamada de API. Pode não ser necessário testar se é possível enviar / receber informações de qualquer serviço da web arbitrário, mas sim se seu código trata e processa sua resposta de uma maneira esperada.

Nesse caso, pode ser melhor refatorar o código que você está tentando testar. Divida a análise / tratamento de resposta para outra classe que aceita um simples Stringe faça seu teste nessa classe injetando respostas de string de amostra.

Isso está mais ou menos seguindo as idéias de Responsabilidade Única e Inversão de Dependência (O S e D em SÓLIDO )

grego
fonte
1

Ok, então eu sei que muitos outros disseram esta resposta antes e podem já estar desatualizados

    when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application);
    when(mockApplication.getFilesDir()).thenReturn(RuntimeEnvironment.application.getFilesDir());

    sharedPref = RuntimeEnvironment.application.getSharedPreferences(KEY_MY_PREF, Context.MODE_PRIVATE);
    sut = new BundleManagerImpl(mockApplication,
            processHtmlBundle, resultListener, sharedPref);

Eu obtive null, porque a parte when () foi DEPOIS da inicialização do sut. Isso pode ajudar alguns de vocês.

também eu tenho o

@RunWith(CustomRobolectricTestRunner.class)
@Config(constants = BuildConfig.class)

no começo da aula

Além disso

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
Karoly
fonte