How to configure SpringConfig.java file for JUnit testing - java

I am using SpringConfig.java instead of SpringConfig.xml. In this class I return:
#Bean(name = "restTemplate")
public RestTemplate restTemplate() {
return new RestTemplate();
}
instead of writing
And I am using #Autowired and I am using SpringJunit4Classrunner. How can I configure SpringConfig.java and my JUnit test file to do proper dependency injection.

If you want to use only annotations, you don't have to use #Autowired in other classes, all configurations have to be in SprinConfig.java. have a look in
SpringConfig Annotations
For Junit Configuration, you have to configure dependencies in pom.xml like this:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
and your test class will be like this:
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import package.SpringConfig;
public class SimpleTests {
#Test
public void Test() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
SpringConfig.class);
//...
}

Place the following annotations above your class delcaration in your unit test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = SpringConfig.class),

Related

how to disable #PreAuthorize for tests?

I use Spring Boot with Spring Security. I want to disable security so that #PreAuthorize. I partially managed to do it, but there is still an error.
security is partially disabled. but some part is included. finally, I would like to disable security for certain tests
org.springframework.security.access.AccessDeniedException: Access denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73) ~[spring-security-core-5.5.3.jar:5.5.3]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:238) ~[spring-security-core-5.5.3.jar:5.5.3]
This is my controller
#PreAuthorize("hasAnyAuthority('ADMIN')")
#GetMapping("/hello")
fun hello(): String {
return "Hello"
}
This my Spring Configutarion for tests.
#TestConfiguration
#Order(1)
class TestSecurityConfig : WebSecurityConfigurerAdapter() {
#Override
override fun configure(httpSecurity: HttpSecurity) {
http.authorizeRequests()
.anyRequest().permitAll();
http.csrf().disable()
.httpBasic().disable()
.formLogin().disable()
.logout().disable();
}
}
And finally my test class:
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = [TestSecurityConfig::class])
#ActiveProfiles("test")
#ExtendWith(SpringExtension::class)
class HelloControllerTest {
#LocalServerPort
private var port: Int = 8281
#Value("#{servletContext.contextPath}")
private lateinit var contextPath: String
private lateinit var url: String
#Autowired
private lateinit var testRestTemplate: TestRestTemplate
#BeforeAll
fun setUp() {
url = UriComponentsBuilder
.fromUriString("http://localhost")
.port(port)
.path(contextPath)
.pathSegment("hello")
.toUriString()
}
#Test
fun hello() {
val responseEntity = testRestTemplate.getForEntity(url, String::class.java)
assertNotNull(responseEntity)
assertEquals(HttpStatus.OK, responseEntity.statusCode)
val response = responseEntity.body
}
Usually you can use mock system for authorization with spring-test
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
For web FLUX
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.beans.factory.annotation.Autowired;
#WithMockUser
#SpringBootTest
#AutoConfigureWebTestClient
class MyTest {
#Autowired
WebTestClient rest;
#Test
void fooTest() {
StatusAssertions.isOk(rest.get().uri(path).exchange().expectStatus())
}
}
For web MVC
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.beans.factory.annotation.Autowired;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#WithMockUser
#AutoConfigureMockMvc
#SpringBootTest
class MyTest {
#Autowired
private MockMvc mvc;
#Test
void fooTest() {
mvc.perform(get("path")).andExpect(status().isOk())
}
}

Unable to mock with Quarkus, NullPointer exception and cannot find relevant imports

I am trying to write unit tests for Quarkus using Mockito, but I fail mocking things.
Here is a minimal (not) working example :
package com.my.package;
import io.quarkus.test.junit.QuarkusTest;
import org.mockito.Mockito;
import org.mockito.Mock;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
#QuarkusTest
public class LoadCalculatorServiceTest {
public class Foobar {
public int baz;
public void setBaz(int baz) {
this.baz = baz;
}
public int getBaz() {
return this.baz;
}
}
#Mock
Foobar foobar;
// Foobar foobar = new Foobar(); // doesn’t work either
#Test
public void myTest() {
Mockito.when(foobar.getBaz()).thenReturn(4); // NullPointer
Assertions.assertEquals(4,foobar.getBaz());
}
}
The test crashes on a NullPointer.
I read such issues may be fixed by annotating the test with #RunWith(MockitoJUnitRunner.class), #ExtendWith(MockitoExtension.class) (which for some reason I expected #QuarkusTest to do anyway ?), however I fail to find the correct imports to load them.
I tried org.junit.jupiter.api.MockitoExtension, org.junit.runner.RunWith and variations, without success.
Here is the relevant part of my pom.xml :
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-mockito</artifactId>
<scope>test</scope>
</dependency>
What am I missing ?
I figured the original code works with plain-style mocks :
Foobar foobar = Mockito.mock(Foobar.class);
So the question is actually how to make the #Mock annotation work ? There are several things needed for that :
The #RunWith annotation has been replaced (or should we say upgraded) by #ExtendWith in JUnit5. It can be imported in Quarkus using import org.junit.jupiter.api.extension.ExtendWith;.
#RunWith is usually used as #ExtendWith(MockitoExtension.class). MockitoExtension can be imported in Quarkus using import org.mockito.junit.jupiter.MockitoExtension;. Beware that the mockito-junit-jupiter dependency (from the org.mockito group) must be added to the pom.xml, since the quarkus-junit5-mockito packages do not depend on it.
Mocks have to be initialized by MockitoAnnotations.initMocks() before the tests. Note that although it may seem to make more sense to use #BeforeAll for the setup function, apparently it is not the point of this annotation and one should use #BeforeEach (the former needs the setup to be static, and IIUC the setup function will be called before each test anyway).
Then finally the #Mock annotation should work.
To summarize, the original code would become :
package com.my.package;
import io.quarkus.test.junit.QuarkusTest;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
#QuarkusTest
#ExtendWith(MockitoExtension.class)
public class LoadCalculatorServiceTest {
public class Foobar {
public int baz;
public void setBaz(int baz) {
this.baz = baz;
}
public int getBaz() {
return this.baz;
}
}
#BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Mock
Foobar foobar;
#Test
public void myTest() {
Mockito.when(foobar.getBaz()).thenReturn(4);
Assertions.assertEquals(4,foobar.getBaz());
}
}
with the following addition to the pom.xml :
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
I'm using quarkus 1.8.1.Final, with mockito 3.6.0, I had the same issue with #Mock annotation and I followed the answer from Skippy le Grand Gourou and it didn't work, so I deleted the #QuarkusTest annotation, and delete de MockitoAnnotations.initMocks(this) method, my mockito version has deprecated this, then the test run with the #Mock annotation. I'm new doing Quarkus so I don't know very well the side effects of removing #QuarkusTest

Spring Data JPA Repository wiring for integration test not working

I'm trying to write an integration test for my TemplateRepository using an inmemory db(HSQL).
public interface TemplateRepository extends CrudRepository<TemplateEntity, String> {
TemplateEntity findByIdAndTemplateName(String id, String templateName);
void deleteByIdAndTemplateName(String cifId, String templateName);
}
This is the test class so far:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestConfig.class})
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest("server.port:0")
public class TemplatesRepositoryTest {
#Autowired
private TemplateRepository templateRepository;
private EmbeddedDatabase db;
#Before
public void setUp() {
db = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("sql/create-db.sql")
.addScript("sql/insert-data.sql")
.build();
}
#Test
public void test1() { }
}
Which is using this context config:
#Configuration
public class TestConfig {
#Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder
.setType(EmbeddedDatabaseType.HSQL)
.addScript("sql/create-db.sql")
.addScript("sql/insert-data.sql")
.build();
return db;
}
}
And the application class:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And the declared dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
The autowiring of the repository to the test class is not working. I'm getting the following error:
11:25:57.300 [main] ERROR o.s.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener#5f3a4b84] to prepare test instance [TemplatesRepositoryTest#4eb7f003]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'TemplatesRepositoryTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private TemplateRepository TemplatesRepositoryTest.templateRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [TemplateRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I have tried the solutions in all the related topics found, but none seems to fix the problem. Could someone point out what I'm missing here?
I'm using SpringBoot 1.3.1.RELEASE and SpringDataJpa 1.9.2.RELEASE.
I was fighting the same issue and found that when using autoconfiguration for CrudRepository, PagingAndSortingRepository and JpaRepository one should not call initialization scripts within DataSource bean as the content of the in-memory database as H2 is overwritten by the DatabasePopulator bean. Try the configuration code as below:
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
#Configuration
public class TestConfig {
#Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).build();
return db;
}
#Bean
public DatabasePopulator databasePopulator(DataSource dataSource) {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(true);
populator.setIgnoreFailedDrops(true);
populator.addScript(new ClassPathResource("sql/create-db.sql"));
populator.addScript(new ClassPathResource("sql/insert-data.sql"));
try {
populator.populate(dataSource.getConnection());
} catch (SQLException ignored) {
}
return populator;
}
}
In case of "solid" database, as for example MySQL, one may explicitly provide NULL value:
#Bean
public DatabasePopulator databasePopulator() {
return null;
}
Hope it solves your problem

Spring boot, disable security for tests

I use spring boot version "1.3.0.M5" (I also tried version "1.2.5.RELEASE"). I added spring security:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
and code:
#SpringBootApplication
public class SpringBootMainApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMainApplication.class, args);
}
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/sampleentity").authenticated()
.and().authorizeRequests()
.and().formLogin().permitAll()
.and().logout().permitAll().logoutUrl("/logout")
.logoutSuccessUrl("/");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
#RestController
#RequestMapping("/api/sampleentity")
public class SampleEntityController {
#RequestMapping(method= RequestMethod.GET)
public Iterable<SampleEntity> getAll() {
return ImmutableSet.of();
}
#RequestMapping(method=RequestMethod.POST)
#ResponseStatus(value= HttpStatus.CREATED)
public SampleEntity create(#RequestBody SampleEntity sampleEntity) {
return sampleEntity;
}
}
and test that is failing when /api/sampleentity is access: org.springframework.web.client.HttpClientErrorException: 403 Forbidden (...)
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = SpringBootMainApplication.class)
#WebAppConfiguration
#IntegrationTest({"server.port=0"})
public class SampleEntityTest {
#Value("${local.server.port}")
private int port;
private String url;
private RestTemplate restTemplate;
#Autowired
private ApplicationContext context;
#BeforeClass
public static void authenticate(){
//ONE TRY
// Authentication authentication =
// new UsernamePasswordAuthenticationToken("user", "password",
// AuthorityUtils.createAuthorityList("USER")); //tried "ROLE_USER"
// SecurityContextHolder.getContext().setAuthentication(authentication);
}
#Before
public void setUp() {
url = String.format("http://localhost:%s/api/sampleentity", port);
restTemplate = new RestTemplate();
//ANOTHER TRY
// AuthenticationManager authenticationManager = context.getBean(AuthenticationManager.class);
// Authentication authentication = authenticationManager
// .authenticate(new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("USER"))); //tried "ROLE_USER"
// SecurityContextHolder.getContext().setAuthentication(authentication);
}
//THIS METHOD SHOULD WORK !
#Test
//ANOTHER TRY
//#WithMockUser(username="user",password = "password", roles={"USER"})//tried "ROLE_USER"
public void testEntity_create() throws Exception {
SampleEntity sampleEntity = create("name", 1);
ResponseEntity<SampleEntity> response = restTemplate.postForEntity(url, sampleEntity, SampleEntity.class);
assertEquals(HttpStatus.CREATED, response.getStatusCode());
}
private SampleEntity create(String name, int id) {
SampleEntity entity = new SampleEntity();
entity.setName(name);
entity.setId(id);
return entity;
}
}
When I run application from main() and access url:
http://localhost:8080/api/sampleentity
I am redirected to login page.
How can I run my test and disable security or just log in user ?
--my solution: exclude security from the test using profiles:
#SpringBootApplication
#EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class})
public class SpringBootMainApplication {body the same}
#EnableWebSecurity
#Import(SecurityAutoConfiguration.class)
#Profile("!test")
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {body the same}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = SpringBootMainApplication.class)
#WebAppConfiguration
#IntegrationTest({"server.port=0"})
#ActiveProfiles("test")
public class SampleEntityTest {body the same}
You have to do some changes to your config and test to solve your problem(s).
First I'll explain why your solution isn't working:
The Spring RestTemplate class is a possible way to access your REST service but lacks some header informations the way it is constructed (Which doesn't mean it's impossible with the RestTemplate). Thats why the authentication didn't work.
My first solution attempt isn't working because of the usage of the RestTemplate class, as the RestTemplate request is likely to create a new session. It sets an entirely different environment. My code works if you want to test Methods secured with the #PreAuthorize annotation but only if you want to execute such a method directly in your test and you need a valid authentication.
You can't automatically authorize any user as of your current spring security configuration.
Second, here are the necessary changes to your code:
First the configuration class
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER" );
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().csrf().disable()
.authorizeRequests().antMatchers("/api/sampleentity").authenticated()
.and().authorizeRequests().antMatchers("/users").hasRole("ADMIN")
.and().formLogin().permitAll()
.and().logout().permitAll().logoutUrl("/logout")
.logoutSuccessUrl("/");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
I had to add httpBasic Authentication support (to enable authentication via http header attribute) and I disabled csrf tokens (the latter just for convenience, you should reenable them according to criticality of your application).
And second the Testclass:
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import javax.servlet.Filter;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.http.MockHttpOutputMessage;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = SpringBootMainApplication.class)
#WebAppConfiguration
#IntegrationTest({ "server.port=0" })
public class SampleEntityTest {
private String url;
private MockMvc mockMvc;
private HttpMessageConverter mappingJackson2HttpMessageConverter;
private MediaType contentType = new MediaType(
MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
#Autowired
private WebApplicationContext webApplicationContext;
#Autowired
private Filter springSecurityFilterChain;
#Autowired
void setConverters(HttpMessageConverter<?>[] converters) {
for (HttpMessageConverter hmc : Arrays.asList(converters)) {
if (hmc instanceof MappingJackson2HttpMessageConverter) {
this.mappingJackson2HttpMessageConverter = hmc;
}
}
Assert.assertNotNull("the JSON message converter must not be null",
this.mappingJackson2HttpMessageConverter);
}
#Before
public void setUp() {
url = "/api/sampleentity";
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilters(springSecurityFilterChain).build();
}
#Test
public void testEntityGet() throws Exception {
mockMvc.perform(
get(url)
.with(httpBasic("user", "password")))
.andExpect(status().isOk());
}
#Test
public void testEntityPost() throws Exception {
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setName("name");
sampleEntity.setId(1);
String json = json(sampleEntity);
mockMvc.perform(
post(url)
.contentType(contentType)
.content(json)
.with(httpBasic("user", "password")))
.andExpect(status().isCreated());
}
protected String json(Object o) throws IOException {
MockHttpOutputMessage mockHttpOutputMessage = new MockHttpOutputMessage();
this.mappingJackson2HttpMessageConverter.write(o,
MediaType.APPLICATION_JSON, mockHttpOutputMessage);
return mockHttpOutputMessage.getBodyAsString();
}
}
I have used the spring/ spring security test approach here.
Versions used:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>4.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
If you want to test your rest api i can recommend you the Postman plugin for Chrome. As that can help you identify the problem much faster.
I hope this helps you to finally solve your problem.
If you want to see what's being auto-configured, launch your web app and access the autoconfig endpoint (e.g., http://localhost:8080/autoconfig). Then search for 'Security' to see which 'AutoConfiguration' classes are being detected.
You can then disable auto-configuration of security by excluding those classes like this:
#EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class, ManagementSecurityAutoConfiguration.class })
Of course, you won't want to exclude them for production deployments. Thus you'll need to have a separate #Configuration class for production and tests.
Or if you want a detailed answer go for below-mentioned steps
Add annotation #Profile(value = {"development", "production"}) to my implementation of WebSecurityConfigurerAdapter
#Configuration
#EnableWebSecurity
#Profile(value = {"development", "production"})
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
Now, in test/resources, create application-test.yml to define properties for test profile and add this -
# Security enable/disable
security:
basic:
enabled: false
Now, to your test cases, add this annotation to apply the active profile #ActiveProfiles(value = "test"). This is how my class looked -
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#ActiveProfiles(value = "test")
#IntegrationTest({"server.port=0"})
public class SampleControllerIntegrationTest {
Doing this will disabled security for tests.
Best of luck!!!

Mockito throws NotAMockException using spring mvc injection

Hy guys,
I am trying to make a test using mockito on a web application that uses spring mvc.
When it executes this line "Mockito.reset(notificacaoRepositoryMock);" it throws "org.mockito.exceptions.misusing.NotAMockException: Argument should be a mock, but is: class com.sun.proxy.$Proxy40"
I saw that in am example and it worked, I can't find what I am doing wrong here.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestContext.class, WebAppConfig.class})
#WebAppConfiguration
public class NotificacaoControllerTest {
private MockMvc mockMvc;
#Autowired
private NotificacaoRepository notificacaoRepositoryMock;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setUp() {
// *** Error here ***
Mockito.reset(notificacaoRepositoryMock);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
My TestContext is:
#Configuration
public class TestContext {
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("i18n/messages");
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
#Bean
public NotificacaoRepository notificacaoRepository() {
return Mockito.mock(NotificacaoRepository.class);
}
}
The class I want mock is a CrudRepository interface
public interface NotificacaoRepository extends CrudRepository<Notificacao, Long> {
}
and, I think, the relevant part of my pom.xml is (spring versions and mockito)
<properties>
<hibernate.version>4.2.0.Final</hibernate.version>
<mysql.connector.version>5.1.21</mysql.connector.version>
<spring.version>4.1.6.RELEASE</spring.version>
<spring.data.version>1.8.0.RELEASE</spring.data.version>
</properties>
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring.data.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.3.RELEASE</version>
<scope>test</scope>
</dependency>
UPDATE
#jfcorugedo i tryed exactly what you said but I keep receiving the same error. My test context is just
#Configuration
public class TestContext {
#Bean
#Primary
public NotificacaoRepository notificacaoRepository() {
return Mockito.mock(NotificacaoRepository.class);
}
}
and my test class now is:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {WebAppConfig.class})
#WebAppConfiguration
#Import({TestContext.class})
public class NotificacaoControllerTest {
#Autowired
NotificacaoRepository notificacaoRepositoryMock;
#Before
public void setUp() {
Mockito.reset(notificacaoRepositoryMock); // Error >> org.mockito.exceptions.misusing.NotAMockException: Argument should be a mock, but is: class com.sun.proxy.$Proxy55
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
This is because Spring create a proxy around your bean.
Try to not inject mock using Spring
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestContext.class, WebAppConfig.class})
#WebAppConfiguration
public class NotificacaoControllerTest {
private MockMvc mockMvc;
private NotificacaoRepository notificacaoRepositoryMock;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setUp() {
notificacaoRepositoryMock = Mockito.mock(NotificacaoRepository.class);
Mockito.reset(notificacaoRepositoryMock);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
As far as I know, you are trying to replace the spring bean with a mock version.
In that case you have to annotate the method that produces your mock with the annotation #Primary, so Spring could choose the mock object by default in each autowired field (of course if it doesn't have any qualifier).
If you're trying to use a Spring context in your test that has some real beans and other mock beans, you have to follow this steps:
Create a #Configuration class in your test folder that inject a mock instance of the beans you want to mock
Import this configuration class in your test
For instance:
Configuration class that injects the mock
import static org.mockito.Mockito.mock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import xxx.xxx.xxx.NotificacaoRepository;
#Configuration
public class MockConfigurer {
#Bean
#Primary
public NotificacaoRepository registerMock() {
return mock(NotificacaoRepository.class);
}
}
Test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {WebAppConfig.class})
#WebAppConfiguration
#Import({MockConfigurer.class})
public class NotificacaoControllerTest {
//Now the instance injected here should be a mock object
#Autowired
private NotificacaoRepository notificacaoRepositoryMock;
...
}

Categories

Resources