In my Java application I am trying to test the following service method with a Unit Test:
#Service
#EnableCaching
#RequiredArgsConstructor
public class LabelServiceImpl implements LabelService {
private static final String CACHE_NAME = "demoCache";
private final LabelRepository labelRepository;
#Override
public List<LabelDTO> findByUuid(UUID uuid) {
final Label label = labelRepository.findByUuid(uuid)
.orElseThrow(() -> new EntityNotFoundException("Not found."));
final List<LabelDTO> labelList = labelRepository.findByUuid(uuid);
return labelList;
}
}
Here is my Unit Test:
#Import({CacheConfig.class, LabelServiceImpl.class})
#ExtendWith(SpringExtension.class)
#EnableCaching
#ImportAutoConfiguration(classes = {
CacheAutoConfiguration.class,
RedisAutoConfiguration.class
})
#RunWith(MockitoJUnitRunner.class)
public class CachingTest {
#InjectMocks
private LabelServiceImpl labelService;
#Autowired
private CacheManager cacheManager;
#Mock
private LabelRepository labelRepository;
#Test
void givenRedisCaching_whenFindUuid_thenReturnFromCache() {
//code omitted
LabelDTO labelFromDb = labelService.findByUuid(uuid);
LabelDTO labelFromCache = labelService.findByUuid(uuid);
verify(labelRepository, times(1)).findByUuid(uuid);
}
}
When I use #Autowired for LabelServiceImpl in the Unit Test, I get "Nullpointer exception" error. If I use #InjectMocks annotation for that instance, then there is no error, but no caching is done (it calls labelService.findByUuid 2 times instead of 1).
I think I made a mistake related to the annotations in Unit Test class, but I tried many different combinations and cannot solve the problem.
So, how can I fix the problem?
Update: Finally I fixed the problem by using the following approach. However, I also had to update the mockito-core version from 3.3.3 to 3.7.0 as shown below. Otherwise I was getting "java.lang.NoSuchMethodError: org.mockito.MockitoAnnotations.openMocks(Ljava/lang/Object;)Ljava/lang/AutoCloseable;" error.
pom.xml:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.7.0</version>
<scope>test</scope>
</dependency>
CachingTest:
#ExtendWith(MockitoExtension.class)
#SpringBootTest
public class CachingTest {
#Autowired
#InjectMocks
private LabelServiceImpl labelService;
#MockBean
private LabelRepository labelRepository;
#Test
public void givenRedisCaching_whenFindUuid_thenReturnFromCache() {
//code omitted
LabelDTO labelFromDb = labelService.findByUuid(uuid);
LabelDTO labelFromCache = labelService.findByUuid(uuid);
verify(labelRepository, times(1)).findByUuid(uuid);
assertEquals(labelFromDb, labelFromCache);
}
}
Mockito does not simulate your springt boot application. It just mocks the annotated objects and injects your mock objects into your labelService.
On the other hand to test a spring boot application #Autowired is not enough.
You have to build a Spring Boot Integration Test.
To do this annotate your Test with #SpringBootTest.
This initializes a real Application Context.
try to autowire, LabelService
package com.demo;
import org.springframework.stereotype.Service;
#Service
public class LabelService
{
public String getLabel()
{
return "Test Label " + System.currentTimeMillis();
}
}
package com.demo;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
#SpringBootTest
public class CachingTest
{
#Autowired
private LabelService labelService;
#Test
public void testLabelService()
{
assertNotNull(labelService);
}
}
this works
Recently I have added Spring Security to my Spring Boot project using the following class:
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig {
}
as result, by default all my URLs are now protected with authentication and a self-generated password.
The problem is that all tests in a #WebMvcTest class that I used for unit-testing a controller:
#RunWith(SpringRunner.class)
#WebMvcTest(SomeController.class)
public class SomeControllerTest {...}
are now failing everywhere because of lack of authorization.
Question: can I tell #Test methods to ignore authorization so they keep succeeding as before?
How can I prevent the #EnableWebSecurity config class from being picked on a specific #WebMvcTest unit testing class?
I would like the tests already in place to be able to still go through and to test the authentication features separately later on.
So far I have tried to use a nested config class in the testing class in order to exclude security configs:
#RunWith(SpringRunner.class)
#WebMvcTest(SomeController.class)
public class SomeControllerTest {
#Configuration
#EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class})
static class ContextConfiguration { }
....}
but it seems not to work.
NOTE : I am using Spring Boot 1.5.8
For me in Spring Boot 2.2.4 (JUnit5) the below seems to have worked and bypass the security filter.
#ExtendWith(SpringExtension.class)
#WebMvcTest(SomeController.class)
#AutoConfigureMockMvc(addFilters = false)
public class SomeControllerTest {
...
Note: this simply disables any filters in the SpringSecurity configuration. It won't disable the security completely. In other words it will still bootstrap security without loading any filters.
You can set secure=false in the #WebMvcTest annoation.
It will skip the spring security MockMvc auto configuration in your Test
#WebMvcTest(controllers = SomeController.class, secure = false)
public class SomeControllerTest {
Note by the author:
As of 2021, this answer has been obsolete for a few years and it probably won't work for you.
In Spring Boot 2.2.6, #WebMvcTest is meta annotated with #AutoConfigureWebMvc which auto-configure org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration as you can see in spring.factories of spring-boot-test-autoconfigure.jar
So you just have to exclude SecurityAutoConfiguration in your test to disable Spring Security :
#WebMvcTest(excludeAutoConfiguration = SecurityAutoConfiguration.class)
In Spring Boot 2.4 both secure flags were removed and none of the answers here actually work.
I ended up excluding all the security myself and wrapping it around in a custom annotation.
import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import java.lang.annotation.*;
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#WebMvcTest(excludeFilters = {#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = WebSecurityConfigurer.class)},
excludeAutoConfiguration = {SecurityAutoConfiguration.class,
SecurityFilterAutoConfiguration.class,
OAuth2ClientAutoConfiguration.class,
OAuth2ResourceServerAutoConfiguration.class})
public #interface UnsecuredWebMvcTest {
#AliasFor(annotation = WebMvcTest.class, attribute = "controllers")
Class<?>[] value() default {};
#AliasFor(annotation = WebMvcTest.class, attribute = "controllers")
Class<?>[] controllers() default {};
}
With Spring Security 4+, I find #WithMockUser annotation to be very handy. It provides a mock user and password to test spring security methods annotated with #PreAuthorize or #PostAuthorize. All you need to do is annotate the test method with #WithMockUser. The default role for the user is USER. You can override the default username and role too.
//default
#Test
#WithMockUser
public void getProfile() {
//your test here
}
//with username and roles
#Test
#WithMockUser(username = "john", roles={"ADMIN"})
public void getProfile() {
//your test here
}
NOTE: This annotation can be used for classes.
#WithMockUser(username = "john", roles={"ADMIN"})
public class UsersAdminSecurityTest {
}
This worked for me, using spring boot 2.3.1.
#ExtendWith(SpringExtension.class)
#WebMvcTest(SomeController.class)
#AutoConfigureMockMvc(addFilters = false)
public class SomeControllerTest {
}
I understand this is a specific question for Spring Boot 1.5 but seems a bit old. In order to have a successful OAuth2 secured controller unit test running I applied the following steps, kindly notice I used Spring Boot 2.2.6, Gradle 5.x, and JUnit 5. This mechanism should work the same way deprecated ones based on #AutoConfigureMockMvc(secure = false) or #WebMvcTest(controllers = SomeController.class, secure = false)
This is for a REST API project that is secured (OAuth2) using Microsoft's Azure Active Directory, but essentially this testing strategy should work for any OIDC, OAuth2 configuration.
The trick is to have a Controller test file and annotate it with #WebMvcTest annotation, however, the following parameters are required:
#WebMvcTest(
value = YourController.class
// this disables loading up the WebSecurityConfig.java file, otherwise it fails on start up
, useDefaultFilters = false
// this one indicates the specific filter to be used, in this case
// related to the GreetController we want to test
, includeFilters = {
#ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = YourController.class
)
}
)
Here the configurations that make the test run successfully.
build.gradle
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.grailscoder'
version = '0.0.1-SNAPSHOT'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
ext {
set('azureVersion', "2.2.4")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.microsoft.azure:azure-active-directory-spring-boot-starter'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.5.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
}
dependencyManagement {
imports {
mavenBom "com.microsoft.azure:azure-spring-boot-bom:${azureVersion}"
}
}
test {
useJUnitPlatform()
}
GreetController.java
package com.grailscoder.controller;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
#RequiredArgsConstructor
#RestController
public class GreetController {
#GetMapping("/greets")
#PreAuthorize("hasRole('ROLE_USER')") // This is validating against Active Directory's User role granted to the
// current user.
#ResponseStatus(HttpStatus.OK)
public String getGreetMessage() {
return "Greets from secret controller";
}
}
WebSecurityConfig.java
package com.grailscoder.config;
import com.microsoft.azure.spring.autoconfigure.aad.AADAppRoleStatelessAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#RequiredArgsConstructor
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final AADAppRoleStatelessAuthenticationFilter aadAuthFilter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
http.authorizeRequests()
.antMatchers("/", "/index.html", "/public").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(aadAuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}
application.properties
azure.activedirectory.client-id=xxxxx-AD-client-id-goes-here
azure.activedirectory.session-stateless=true
GreetControllerTest.java
package com.grailscoder.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#WebMvcTest(
value = GreetController.class
// this disables loading up the WebSecurityConfig.java file, otherwise it fails on start up
, useDefaultFilters = false
// this one indicates the specific filter to be used, in this case
// related to the GreetController we want to test
, includeFilters = {
#ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = GreetController.class
)
}
)
class GreetControllerTest {
#Autowired
MockMvc mockMvc;
#Autowired
ObjectMapper objectMapper;
#BeforeEach
void setUp() {
// add setup stuff here
}
#Test
#WithMockUser
void testGreet() throws Exception {
ResultActions result = mockMvc.perform(get("/greets"))
.andExpect(status().isOk());
System.out.println(result.andReturn().getResponse().getContentAsString());
}
}
I understand in order to have a similar test JUnit 4 based with a completely different approach, the following test could be used as a reference (but I haven't tried): https://github.com/spring-projects/spring-security/blob/master/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTests.java
In my case, for Spring Boot version 2.5.4, I'm able to bypass Jwt security by setting useDefaultFilters = false in #WebMvcTest
#WebMvcTest(controllers = YourController.class, useDefaultFilters = false)
public class YourControllerTest {
// Test cases
}
#AutoConfigureMockMvc(addFilters = false)
Just adding addFilters = false resolved this.
I solved the problem by using following annotations and properties:
#WebMvcTest(controllers =
SomeController.class,
excludeAutoConfiguration = {
MySecurityConfig.class,
ManagementWebSecurityAutoConfiguration.class,
SecurityAutoConfiguration.class
}
)
#ContextConfiguration(classes = SomeController.class)
public class SomeControllerTest {
}
NOTE: I' using spring boot 2.6.6, so secure=false didn't work for me!
#AutoConfigureMockMvc(secure = false) does not work because secure is deprecated
what works:
#AutoConfigureMockMvc(addFilters = false)
does not completely disable spring security just bypass its filter chain.
or
#WebMvcTest(excludeAutoConfiguration = {SecurityAutoConfiguration.class})
(and if you are using Spring Boot actuator:
#WebMvcTest(excludeAutoConfiguration = {SecurityAutoConfiguration.class,
ManagementWebSecurityAutoConfiguration.class})
)
Situation and Problem: In Spring Boot, how can I inject one or more mocked classes/beans into the application to do an integration test? There are a few answers on StackOverflow, but they are focused on the situation before Spring Boot 1.4 or are just not working for me.
The background is, that in the code bellow the implementation of Settings relies on third party servers and other external systems. The functionality of Settings is already tested in a unit test, so for a full integration test I want to mock out the dependency to these servers or system and just provide dummy values.
MockBean will ignore all existing bean definitions and provide a dummy object, but this object doesn't provide a method behavior in other classes that inject this class. Using the #Before way to set the behavior before a test doesn't influence the injected object or isn't injected in other application services like AuthenticationService.
My question: How can I inject my beans into the application context?
My test:
package ch.swaechter.testapp;
import ch.swaechter.testapp.utils.settings.Settings;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.test.context.junit4.SpringRunner;
#TestConfiguration
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {MyApplication.class})
public class MyApplicationTests {
#MockBean
private Settings settings;
#Before
public void before() {
Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
}
#Test
public void contextLoads() {
String applicationsecret = settings.getApplicationSecret();
System.out.println("Application secret: " + applicationsecret);
}
}
And bellow a service that should use the mocked class, but doesn't receive this mocked class:
package ch.swaechter.testapp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class AuthenticationServiceImpl implements AuthenticationService {
private final Settings settings;
#Autowired
public AuthenticationServiceImpl(Settings settings) {
this.settings = settings;
}
#Override
public boolean loginUser(String token) {
// Use the application secret to check the token signature
// But here settings.getApplicationSecret() will return null (Instead of Application Secret as specified in the mock)!
return false;
}
}
Looks like you are using Settings object before you specify its mocked behavior.
You have to run
Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
during configuration setup. For preventing that you can create special configuration class for test only.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {MyApplication.class, MyApplicationTest.TestConfig.class})
public class MyApplicationTest {
private static final String SECRET = "Application Secret";
#TestConfiguration
public static class TestConfig {
#Bean
#Primary
public Settings settingsBean(){
Settings settings = Mockito.mock(Settings.class);
Mockito.when(settings.getApplicationSecret()).thenReturn(SECRET);
Mockito.doReturn(SECRET).when(settings).getApplicationSecret();
return settings;
}
}
.....
}
Also I would recommend you to use next notation for mocking:
Mockito.doReturn(SECRET).when(settings).getApplicationSecret();
It will not run settings::getApplicationSecret
When you annotate a field with #MockBean, spring will create a mock of the annotated class and use it to autowire all beans of the application context.
You must not create the mock yourself with
Settings settings = Mockito.mock(Settings.class);
this would create a second mock, leading to the described problem.
Solution :
#MockBean
private Settings settings;
#Before
public void before() {
Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
}
#Test
public void contextLoads() {
String applicationsecret = settings.getApplicationSecret();
System.out.println("Application secret: " + applicationsecret);
}
I am trying to use spock for testing my java based web application. Earlier we used to use, Junit along with Mockito for testing.
I am trying to use #Collaborator and #Subject to autowire my dependencies like we used to use #Mock and #InjectMocks in Mockito.
But it is not working. I am getting the following error.
java.lang.NullPointerException
at com.blogspot.toomuchcoding.spock.subjcollabs.NonConstructorBasedInjector.instantiateSubjectAndSetOnSpecification(NonConstructorBasedInjector.groovy:22)
at com.blogspot.toomuchcoding.spock.subjcollabs.PropertyInjector.tryToInject(PropertyInjector.groovy:16)
at com.blogspot.toomuchcoding.spock.subjcollabs.SubjectsCollaboratorsInterceptor.tryToInjectCandidatesIntoSubject_closure2(SubjectsCollaboratorsInterceptor.groovy:74)
at com.blogspot.toomuchcoding.spock.subjcollabs.SubjectsCollaboratorsInterceptor.tryToInjectCandidatesIntoSubject(SubjectsCollaboratorsInterceptor.groovy:74)
at com.blogspot.toomuchcoding.spock.subjcollabs.SubjectsCollaboratorsInterceptor.intercept_closure1(SubjectsCollaboratorsInterceptor.groovy:69)
at groovy.lang.Closure.call(Closure.java:426)
at groovy.lang.Closure.call(Closure.java:442)
at com.blogspot.toomuchcoding.spock.subjcollabs.SubjectsCollaboratorsInterceptor.intercept(SubjectsCollaboratorsInterceptor.groovy:69)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Below is my test code.
class UserServiceImplSpec extends Specification {
#Collaborator
UserDAO userDAO = Mock()
#Subject
UserService userService
def "should delete a user"(){
given: "given a user to delete"
User userToDelete = make(a(UserMaker.User));
when:
userService.deleteUser(userToDelete.getId());
then:
true
}
}
Below is the URL for the extension I am using for autowiring.
https://github.com/marcingrzejszczak/spock-subjects-collaborators-extension
Below are my dependencies.
testCompile 'org.codehaus.groovy:groovy-all:2.4.5'
testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4'
testCompile "cglib:cglib:2.2"
testCompile 'org.objenesis:objenesis:2.2'
testCompile 'com.blogspot.toomuchcoding:spock-subjects-collaborators-extension:1.1.0'
Below is my UserService and UserServiceImpl classes.
public interface UserService {
public void deleteUser(Long userId);
}
#Service("userService")
#Transactional(readOnly = true)
public class UserServiceImpl implements UserService {
#Autowired
private UserDAO userDAO;
#Autowired
private SecurityUtil securityUtil;
#Override
#Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackForClassName = {"java.lang.Exception" })
public void deleteUser(Long userId) {
log.debug("Deleting an user entry with the user id: {}", userId);
User user = userDAO.findById(userId);
userDAO.delete(user);
}
}
The problem was related to the fact that #Subject annotated class should be an implementation and not an interface.
It's enough to change UserService into UserServiceImpl
you have a problem with inject annotations #Collaborator, #Subject
import com.blogspot.toomuchcoding.spock.subjcollabs.Collaborator
import com.blogspot.toomuchcoding.spock.subjcollabs.Subject
Add dependency:
<dependency>
<groupId>com.blogspot.toomuchcoding</groupId>
<artifactId>spock-subjects-collaborators-extension</artifactId>
<version>1.1.0</version>
<scope>test</scope>
</dependency>
OR
dependencies {
testCompile 'com.blogspot.toomuchcoding:spock-subjects-collaborators-extension:1.1.0'
}
I got a weird warning Method annotated with #Test inside class extending junit3 testcase when using the new ActivityInstrumentationTestCase2 class shipped with Espresso 2.0.
My class looks just like the one that Google provided as an example:
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
import static org.hamcrest.Matchers.notNullValue;
#RunWith(AndroidJUnit4.class)
#LargeTest
public class MyCoolActivityTests extends ActivityInstrumentationTestCase2<MyCoolActivity> {
private MyCoolActivity mActivity;
public MyCoolActivityTests() {
super(MyCoolActivity.class);
}
#Before
public void setUp() throws Exception {
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
mActivity = getActivity();
}
#Test
public void checkPreconditions() {
assertThat(mActivity, notNullValue());
// Check that Instrumentation was correctly injected in setUp()
assertThat(getInstrumentation(), notNullValue());
}
#After
public void tearDown() throws Exception {
super.tearDown();
}
}
I've added all necessary things to the build.gradle:
android {
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
dependencies {
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
}
Is there any way to get this warning away?
ActivityInstrumentationTestCase2 is a JUnit 3 test case because it extends from TestCase.
#Test annotation is a replacement for the test-prefix naming convention used in JUnit 3. JUnit 4 test classes no longer require to extend TestCase or any of its subclasses. In fact JUnit 4 tests cannot extend TestCase, otherwise AndroidJUnitRunner will treat them as JUnit 3 tests.
http://developer.android.com/tools/testing-support-library/index.html#AndroidJUnitRunner
You could either migrate to ActivityTestRule provided by com.android.support.test:rules:0.4 (or later), or stick with JUnit 3.
Another option is InstrumentationRegistry, provided by Espresso 2, which has getInstrumentation(), getContext(), getTargetContext() (and more). These methods provide access to the current instrumentation, test context, and target context in a static manner. This makes it possible to write your own static utility methods for use in JUnit 4 test case classes. These utilities would mimic functionality that is currently only available in the base JUnit 3 test case classes. (This is no longer necessary.)