Mockito throws NotAMockException using spring mvc injection - java

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;
...
}

Related

Spring #Configuration annotation #Autowired service is null

I am using Spring Configuration and Jersey Configuration.
This is my spring configuration:
#Component
#Configuration
#EnableScheduling
#EnableAspectJAutoProxy
#EnableTransactionManagement
#ComponentScan(basePackages = { "my.packages" })
public class SpringConfig {
private static final String MESSAGE_SOURCE_BASE_NAME = "i18n/messages";
#Profile(Profiles.APPLICATION)
#Configuration
#PropertySource("classpath:application.properties")
static class ApplicationProperties {
}
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder(11);
}
#Bean
public TaskScheduler taskScheduler() {
return new ConcurrentTaskScheduler();
}
#Bean
MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename(MESSAGE_SOURCE_BASE_NAME);
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
}
This is my Service class and interface:
public interface DAOService {
User register(User user)
}
#Service
public class DAOServiceImpl implements DAOService {
#Override
User register(User user){
return null;
}
}
This is my jersey resource:
Inside ResourceSecurityService class I want to use #Autowire for DAOService
class, but I get null pointer exception, daoService is always null.
#Component
#Path("/security")
#Produces({ MediaType.APPLICATION_JSON })
public class ResourceDAOService {
#Autowired
private DAOService daoService ; //<--- here daoService is null;
#POST
#Path("/register")
#Consumes({ MediaType.APPLICATION_JSON })
#Transactional
public Response register(User user, #Context HttpServletRequest request,
#Context HttpServletResponse response) throws AppException {
return Response.status(Response.Status.CREATED).entity(securityService.register(user)).build();
}
I am using spring version 4.3.8.RELEASE with the next dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</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>
It could be better if you'd provide a link to your project.
Based on information I see:
make sure you have jersey-spring4 dependency
make sure your Jersey version compatible with integration dependency
check out your project configuration
I advice you to use Spring Boot with auto configurations.

Spring 4 TestNG +#Autowired

Have a class in the package com.conf
#Configuration
public class WebConfTest {
#Autowired
private Environment environment;
}
and unit test into com.service
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { WebConfTest.class })
public class DMSServiceImplTest {
#Autowired
WebConfTest webConfTest;
#Test
public void testConnect() throws Exception {
}
}
test dependency :
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
In the IDEA navigation between beans work. But WebConfTest== null if I run test.
What is wrong?
Thanks.
#RunWith is for junit runner.
If you want to run tests with TestNG, you need to extends AbstractTestNGSpringContextTests.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#testcontext-support-classes-testng

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

How to configure SpringConfig.java file for JUnit testing

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),

Job run in #Scheduled does not invoke spring data jpa save

I've scheduled a job with annotation #Scheduled, which was supposed to process data and save it to database using spring data jpa. The save method was invoked without any exceptions but there was no insert to database. In the same annotated method I invoked findAll method which worked fine and fetched data. What could be a reason?
#Repository
public interface PossibleOfferLinkRepository extends PagingAndSortingRepository<PossibleOfferLink, Long> {
}
#Configuration
#ComponentScan
#EnableAutoConfiguration
#Import({Scheduler.class})
#EntityScan(basePackages="model_package")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#EnableScheduling
#ConditionalOnProperty(value= "property_name")
public class Scheduler {
...
#Scheduled(fixedRate=100000)
public void scheduleCrawlerJob() throws MalformedURLException {
Iterable<PossibleOfferLink> links = repo.findAll();
PossibleOfferLink link = repo.save(new PossibleOfferLink(new URL("...")));
}
}
Maven
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.8.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-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.182</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
<version>${easytesting.version}</version>
</dependency>
</dependencies>
Finally i solved this issue in this way :
Added #EnableTransactionManagement in Application class and also added
PlatformTransactionManager Bean. Check the bellow code:
#Autowired
private EntityManagerFactory entityManagerFactory;
#Bean
public PlatformTransactionManager transactionManager()
{
return new JpaTransactionManager(entityManagerFactory);
}
Here is the imports :
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
In my scheduler code added bellow code:
#Scheduled(fixedRate = 60 *10*1000)
#Transactional(propagation=Propagation.REQUIRES_NEW)
public void reportCurrentTime() {
doDatabaseTransaction();
}
Here is the imports :
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
Hope this will solve your problem :)
Your problem is due to there aren't Transaction in progress to commit.
Cause:
javax.persistence.TransactionRequiredException: no transaction is in progress
Here an example on how to configure transaction manager by annotation.
Here the reference
#Configuration
#EnableTransactionManagement
public class PersistenceJPAConfig{
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
...
}
#Bean
public PlatformTransactionManager transactionManager(){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
entityManagerFactoryBean().getObject() );
return transactionManager;
}
}
Add on scheduleCrawlerJob #Transactional
#Scheduled(fixedRate=100000)
#Transactional
public void scheduleCrawlerJob() throws MalformedURLException {
Iterable<PossibleOfferLink> links = repo.findAll();
PossibleOfferLink link = repo.save(new PossibleOfferLink(new URL("...")));
}
I got such issue solved with wrapping the body of scheduleCrawlerJob() to a separate method annotated with #Transactional of another class and creating a method annotated with #Async that is called from scheduleCrawlerJob()
So overall chain of calls would look like:
Scheduled -> Async -> Transactional
P.S. don't forget to add #EnableAsync to the configuration

Categories

Resources