I am trying to write an integration test using AbstractTransactionalJUnit4SpringContextTests. I want to use executeSQLScript method of this class.
However, when executeSQLScript method is called, it throws NullPointerException because simpleJdbcTemplate parameter of class AbstractTransactionalJUnit4SpringContextTests is not getting initialized.
My code looks as given below:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"classpath:test-services-spring-context.xml"})
#TransactionConfiguration(transactionManager = "promoTransactionManager")
public class PromoBrickDAOIT extends AbstractTransactionalJUnit4SpringContextTests {
#Autowired
private PromoBricksDAO promoBricksDAO;
#Before
public void setUp(){
executeSqlScript("classpath:testdata/sql/PromoBrick_Create.sql", false);
}
#After
public void tearDown(){
}
#Test
public void testPromoBrickGivenBrowseTaxonomyNodeId(){
String btxNodeId = "v1_12";
List<PromoBrick> promoBricks = promoBricksDAO.findByBtxNodeId(btxNodeId);
assertNotNull(promoBricks);
assertEquals(promoBricks.size(), 1);
PromoBrick promoBrick = promoBricks.get(0);
assertNotNull(promoBrick);
}
public void setDataSource (#Qualifier("promoDataSource") DataSource dataSource) {
super.setDataSource(dataSource);
}
}
Thanks in advance for the help!
You're missing #Autowired on your setDataSource() method.
See the last NOTE in the Dependency injection of test fixtures section of the Spring Reference Manual.
Related
I'm using custom crudrespository to persist data in redis. However, I'm unable to autowire custom repository.
All the configuration seems correct and redis is running on my local.
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CustomRepository extends CrudRepository<String,
Long> {
String get(String key);
void put(String key, String value);
}
//////////
public class StorageServiceImpl implements IStorageService {
#Autowired
private CustomRepository respository;
#Override
public void saveParameter() {
this.respository.put("key1","value1");
}
#Override
public String getParameter() {
return this.respository.get("key1");
}
/////
#Service
public interface IStorageService {
void saveParameter();
String getParameter();
}
///////
#SpringBootApplication(scanBasePackages = {"com.example.cache"})
#EnableRedisRepositories(basePackages = {"com.example.cache.repository"})
public class ApplicationConfiguration {
public static void main(String[] args){
SpringApplication.run(ApplicationConfiguration.class, args);
new StorageServiceImpl().saveParameter();
System.out.println(new StorageServiceImpl().getParameter());
}
}
When I try running this application using gradle bootRun, I get
Exception in thread "main" java.lang.NullPointerException
at com.example.cache.impl.StorageServiceImpl.saveParameter(StorageServiceImpl.java:16)
at com.example.cache.ApplicationConfiguration.main(ApplicationConfiguration.java:17)
Not sure what's wrong?
You can't use new on any bean, you need to #Autowire it. The annotations only work with spring managed beans at every level.
Add a new bean with a a storage service and a method that makes your call after it is created.
Also, I can't remember if the spring-boot creates the bean if there is only one implementation but I believe your StorageServiceImpl needs the #Service annotation, not the interface.
Delete this from your ApplicationConfiguration class.
new StorageServiceImpl().saveParameter();
System.out.println(new StorageServiceImpl().getParameter());
Then add this new class.
#Service
public class Startup {
#Autowired
IStorageService storageService;
#PostConstruct
public void init(){
storageService.saveParameter();
System.out.println(storageService().getParameter());
}
}
And you need a config
#Configuration
#EnableRedisRepositories
public class ApplicationConfig {
#Bean
public RedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory();
}
#Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
return template;
}
}
I created filter which logging and saving all requests, this is part of this:
#Component
public class RequestFilter extends OncePerRequestFilter {
#Value("${app.endpoint}")
private String requestMapping;
private final RequestRepository requestRepository;
#Autowired
public RequestFilter(RequestRepository requestRepository) {
this.requestRepository = requestRepository;
}
....
}
When app is running requestMapping is properly readed from spring context, but
when I created test for that filter requestMapping is null
#SpringBootTest
#RunWith(SpringRunner.class)
#AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
#ContextConfiguration(classes = {MyApplication.class})
#AutoConfigureMockMvc
#ActiveProfiles("test")
public class FilterTest {
#Autowired
private WebApplicationContext webApplicationContext;
#Autowired
private RequestRepository requestRepository;
#Autowired
protected MockMvc mockMvc;
#Before
public void setup() {
RequestFilter rpmRequestFilter = new RequestFilter(this.requestRepository);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilter(invalidVpmRequestFilter)
.build();
}
}
And of course in application-test.properties I have configured this property:
app.endpoint=/log/save
Does someone know where the problem can be? Why this is doesnt work in tests?
As M. Deinum pointed out, the problem is that you are creating an instance of RequestFilter and if you want Spring to inject components (#Autowired) or propoerties (#Value) in it, you have to let Spring handle the instantiation as follow :
#....
public class FilterTest {
....
#Autowired
RequestFilter requestFilter;
#Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilter(requestFilter)
.build();
}
}
The following code is the standard method to write a JUnit test for a Mvc controller.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = ApplicationTestCassandra.class)
#WebAppConfiguration
public class TestControllerTests {
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#Before
public void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext).build();
}
#Test
public void testupTimeStart() throws Exception {
this.mockMvc.perform(get("/uptime"))
.andExpect(status().isOk());
}
}
This works fine, but I would like to replace an autowired class with a special class for testing. The class CassandraSimpleConnection is injected via #Autowired in my controller.
I have tried several approaches, but no luck.
The following code fails because of an Mvc 404 error, because I guess my application with the REST interface is not running at all.
#RunWith(SpringJUnit4ClassRunner.class)
//ApplicationTestCassandra is SpringBoot application startpoint class with #SpringBootApplication annotation
//#ContextConfiguration(classes = ApplicationTestCassandra.class, loader = AnnotationConfigContextLoader.class)
#ContextConfiguration(loader = AnnotationConfigWebContextLoader.class)//, classes = {ApplicationTestCassandra.class})
#WebAppConfiguration
public class TestControllerTests {
#Service
#EnableWebMvc
#ComponentScan(basePackages={"blabla.functionalTests"})
static class CassandraSimpleConnection {
public Metadata testConnection(TestConfiguration configuration) {
Metadata metadata = null;
// return metadata;
throw new RuntimeException("Could not connect to any server");
}
}
If I use
#ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = {ApplicationTestCassandra.class})
CassandraSimpleConnection is not replaced with my static class.
Could somebody help me please? The documentation about the annotations is quite confusing.
Read the comments and here is the solution:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { MyApplication.class })
public class MyTests {
#MockBean
private MyBeanClass myTestBean;
#Before
public void setup() {
...
when(myTestBean.doSomething()).thenReturn(someResult);
}
#Test
public void test() {
// MyBeanClass bean is replaced with myTestBean in the ApplicationContext here
}
}
I'm following tutorials for integrating Spring docs into my project but i'm running into nullpointerexception when I run my test.
The errors go away when I take out all the document bits. So when I remove restDocumentation variable, the document bit from the setup method and the test then it passes.
Here is my test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = { ContextConfiguration.class })
#WebAppConfiguration
public class ApiDocs {
#Rule
public RestDocumentation restDocumentation = new RestDocumentation(
"${project.basedir}/target/generated-snippets");
private RestDocumentationResultHandler document;
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Autowired
Config Config;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration(this.restDocumentation)).alwaysDo(this.document).build();
}
#Test
public void getConfig() throws Exception {
this.mockMvc.perform(get("/config").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andDo(document("index"));
}
}
The error that I'm getting(I've slashed out my class package due to privacy):
java.lang.NullPointerException
at org.springframework.test.web.servlet.MockMvc.applyDefualtResultActions(MockMvc.java:195)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:163)
at //.//.//.//.//.ApiDocs.getConfig(ApiDocs.java:67)
at org.springframework.test.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at
org.springframework.restdocs.RestDocumentation$1.evaluate(RestDocumentation.java:59)
at org.springframework.test.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.springframework.test.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.springframework.test.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:75)
at org.springframework.test.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:75)
at org.springframework.test.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
Nothing's assigning a value to your this.document field so it's null. You're passing that into alwaysDo which then causes a NullPointerException.
You need to configure what you want to always happen. For example by adding this to the beginning of your setUp method:
this.document = document("{method-name}",
preprocessRequest(removeHeaders("Foo")),
preprocessResponse(prettyPrint()));
There's more information about this in the documentation.
I am trying to write a unit test for the below Assembler but i keep getting Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler?. I wanted to know how i can mock out the resource creation?
#Component
public class LoginResourceAssembler extends ResourceAssemblerSupport<User, ResourceSupport> {
public LoginResourceAssembler() {
super(User.class, ResourceSupport.class);
}
#Override
public ResourceSupport toResource(User user) {
ResourceSupport resource = new ResourceSupport();
final String id = user.getId();
resource.add(linkTo(MyAccountsController.class).slash(id).slash("accounts").withRel("accounts"));
return resource;
}
}
Instead of changing from a plain unit test to a IMO integration test (given dependency of the spring framework) you could do something like:
#RunWith(MockitoJUnitRunner.class)
public class LoginResourceAssemblerTest {
#InjectMocks
private LoginResourceAssembler loginResourceAssembler;
#Before
public void setup() {
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(new MockHttpServletRequest()));
}
#Test
public void testToResource() {
//...
}
}
I was seeing the error Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler because my test class was annotated with #RunWith(MockitoJUnitRunner.class) and this was not injecting the controller.
To fix this error, i annotated my test case with
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
A working test case in my case
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class LoginResourceAssemblerTest {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#InjectMocks
private LoginResourceAssembler loginResourceAssembler;
#Before
public void setUp() {
initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void testToResource() {
User user = new User();
user.setId("1234");
ResourceSupport resource = loginResourceAssembler.toResource(user);
assertEquals(1,resource.getLinks().size());
assertEquals("accounts",resource.getLinks().get(0).getRel());
assertTrue(resource.getLinks().get(0).getHref().contains("accounts"));
}
}