JUnit Test for Dao and Service with Arquillian - unit-testing

Hi I'm trying to test my Service and Dao layers for a Java EE 7 application.
So I looking for testing solutions follow tutorials using Arquillian with junit test and wildfly remote dependence.
Dao and Service interfaces with relative implementations have been created, following my junit test with Arquillian:
#RunWith(Arquillian.class)
public class GenericServiceTest {
#Inject
private EmployeeService employeeService;
#Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap
.create(JavaArchive.class)
.addAsManifestResource("META-INF/persistence.xml",
"persistence.xml")
.addClasses(EmployeeDao.class, EmployeeDaoImpl.class,
EmployeeService.class, EmployeeServiceImpl.class,
Employee.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
#Test
#Transactional
public void should_crud() {
// Gets all the objects
assertNotNull(employeeService);
Employee employee = employeeService.get(new Integer(1));
assertNotNull(employee);
}
}
Running class as JUnit Test it doesn't work with this error:
Caused by: java.lang.Exception: "WFLYCTL0216: Management resource '[(\"deployment\" => \"test.war\")]' not found"
Test pass if any classes has been added to ShrinkWrap as following:
#RunWith(Arquillian.class)
public class GenericDaoTest {
#Inject
private EmployeeService employeeService;
#Deployment
public static JavaArchive createTestableDeployment() {
final JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
return jar;
}
#Test
public void should_crud() {
}
}
How can I create a working test using arquillian for Java EE 7 adding service class implementations?
And I have To add every Class and Intefaces that have to be called (for example all entities,dao etc classes) or only Service Interface and implementation Class?
Thanks a lot

Since you're developing a javaee application, I would suggest you to create a War archive instead of Jar.
You can add the whole package using
ShrinkWrap.addPackages(true, "com.yourpackage.name") so you don't have to add your classes independently.

If I understand the question correctly you want to test a war archive.
If this is the case you should change
return ShrinkWrap
.create(JavaArchive.class)
to
return ShrinkWrap
.create(WarArchive.class)
In addition you should add your persistence.xml file to the META-INF folder like:
.addAsResource("test-persistence.xml", "META-INF/persistence.xml")
If you want to use the annotation #Transactional in your tests, you need to add a few dependencies to your test scope. If you didn't add them yet you can read at http://arquillian.org/modules/transaction-extension/ what dependencies to add.

Related

#DataJpaTest not loading required classes

I'm attempting to set up some Spring Boot JPA tests using:
package biz.ianw.coindatabase.test;
#RunWith(SpringRunner.class)
#DataJpaTest
public class DbTests {
#Test
public void test1() { ... }
}
I have a service class:
package biz.ianw.coindatabase.database;
//#Service
#Repository
#Transactional(readOnly=false)
public class CoinDbService { ... }
and an application:
package biz.ianw.coindatabase;
#SpringBootApplication
#Slf4j
#Configuration
#EnableEncryptableProperties
public class Main {
#Autowired
CoinDbService dbService;
... }
Starting the test gives the error:
Field dbService in biz.ianw.coindatabase.Main required a bean of type 'biz.ianw.coindatabase.database.CoinDbService' that could not be found.
This is, I assumed, something to do with the type of beans #DataJpaTest loads during startup:
#DataJpaTest can be used if you want to test JPA applications. By
default it will configure an in-memory embedded database, scan for
#Entity classes and configure Spring Data JPA repositories. Regular
#Component beans will not be loaded into the ApplicationContext.
I'm not quite sure why #Service classes should be considered as not required for JPA testing, but I tried to force the matter by annotating it as #Repository instead, but to no avail.
I can manually load the class with #Import(...) but it seems a tad hooky. Is there a better way to tell DataJpaTest what I need for testing?
I am quoting from DataJpaTest documentation where you can find the answer to your question.
Annotation that can be used in combination with
#RunWith(SpringRunner.class) for a typical JPA test. Can be used when
a test focuses only on JPA components.
Using this annotation will disable full auto-configuration and instead
apply only configuration relevant to JPA tests.
By default, tests annotated with #DataJpaTest will use an embedded
in-memory database (replacing any explicit or usually auto-configured
DataSource). The #AutoConfigureTestDatabase annotation can be used to
override these settings.
If you are looking to load your full application configuration, but
use an embedded database, you should consider #SpringBootTest combined
with #AutoConfigureTestDatabase rather than this annotation.

unable to launch spring-data-rest unit test, RepositoryRestResource not available for #Autowire

I'm porting an app across from JDBC / REST to spring-data-rest and my one and only unit test with fails with the error
NoSuchBeanDefinitionException:
No qualifying bean of type 'com.xxx.repository.ForecastRepository' available
The app was retro-fitted with spring-boot just previously, and now I'm trying to put a new layer in place with spring-data-rest on top of spring-data-jpa.
I'm attempting to work out the correct Java-config according to
Custom Test Slice with Spring Boot 1.4
but I had to deviate from the idiomatic approach because
the #WebMvcTest annotation doesn't suppress the security module which causes the test to fail
the #MockMvcAutoConfiguration fails due to missing dependencies unless I specify #SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) (see here)
#WebMvcTest and #SpringBootTest are mutually exclusive since they both specify #BootstrapWith and can't run together
So this is the closest I've got but Spring can't locate my #RepositoryRestResource repository:
Repository
#RepositoryRestResource(collectionResourceRel = "forecasts", path = "forecasts")
public interface ForecastRepository extends CrudRepository<ForecastExEncoded,
Long> {
JUnit Test
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK,
classes = {TestRestConfiguration.class})
public class ForecastRestTests {
#Autowired
private MockMvc mockMvc;
#Autowired
private ForecastRepository forecastRepository;
#Before
public void deleteAllBeforeTests() throws Exception {
forecastRepository.deleteAll();
}
#Test
public void shouldReturnRepositoryIndex() throws Exception {
mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk()).andExpect(
jsonPath("$._links.forecasts").exists());
}
}
Configuration
#OverrideAutoConfiguration(enabled = false)
#ImportAutoConfiguration(value = {
RepositoryRestMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
WebMvcAutoConfiguration.class,
MockMvcAutoConfiguration.class,
MockMvcSecurityAutoConfiguration.class
})
#Import({PropertySpringConfig.class})
public class TestRestConfiguration {}
Also tried...
I tried to configure the unit test with just #WebMvcTest and this #ComponentScan below from How to exclude AutoConfiguration from Spring Boot), in an attempt to simplify it all, however the excludeFilters had no effect.
#ComponentScan(
basePackages="com.xxx",
excludeFilters = {
#ComponentScan.Filter(type = ASSIGNABLE_TYPE,
value = {
SpringBootWebApplication.class,
JpaDataConfiguration.class,
SecurityConfig.class
})
})
I've set Spring's logging to trace because all I can do at this point is try to find clues as to what is happening from log output. So far though without any luck.
I can see in the logging that RepositoryRestConfiguration is loading, but obviously it isn't fed with the right info and I am unable to work out how that is done, after googling and pouring over the Spring docs and API. I think I must have read every relevant question here on SO .
Update 2016-11-16 10:00
One thing I see in the logs which concerns me is this:
Performing dependency injection for test context [DefaultTestContext#2b4a2ec7 [snip...]
classes = '{class com.xxx.TestRestConfiguration,
class com.xxx.TestRestConfiguration}',
i.e. the context lists the configuration class twice. I specified the config class (once only) on the #SpringBootTest#classes annotation. But if I leave off the #classes from the annotation, Spring Boot finds and pulls in all the config via the #SpringBootApplication class.
So is that a hint that I am specifying the configuration in the wrong place? How else would I do it?
After way too much time, I settled on this approach.
Custom Test Slice with Spring Boot 1.4 looked promising but I couldn't get anywhere with it.
While going over and over
Accessing JPA Data with REST
I realised I had to include the JPA setup because spring-data-rest is using them directly - no chance to mock them or run unit tests without an embedded database.
At least not as far as I understand it. Maybe it is possible to mock them and have spring-data-rest run on the mocks against test data, but I think spring-data-rest and spring-data are probably too tightly coupled.
So integration testing it must be.
In the Spring source code provided with the articles above
gs-accessing-data-rest/ApplicationTests.java
the logging shows Spring Boot pulling in the whole configuration for the application context.
So that my SpringBootApplication class is avoided and the security module isn't loaded up, I set up my tests like this:
#RunWith(SpringRunner.class)
#SpringBootTest
#ContextConfiguration(classes = {
JpaDataConfiguration.class,
TestJpaConfiguration.class,
TestRestConfiguration.class,
PropertySpringConfig.class})
public class ForecastRestTests {
#SuppressWarnings("SpringJavaAutowiringInspection")
#Autowired
private MockMvc mockMvc;
#Autowired
private ForecastRepository forecastRepository;
#Before
public void deleteAllBeforeTests() throws Exception {
forecastRepository.deleteAll();
}
#Test
public void shouldReturnRepositoryIndex() throws Exception {
mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk()).andExpect(
jsonPath("$._links.forecasts").exists());
}
}
with these configuration classes:
#Configuration
#EnableJpaRepositories(basePackages = {"com.bp.gis.tardis.repository"})
#EntityScan(basePackages = {"com.bp.gis.tardis.type"})
public class JpaDataConfiguration {
and
#Configuration
#OverrideAutoConfiguration(enabled = false)
#ImportAutoConfiguration(value = {
CacheAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class,
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
TransactionAutoConfiguration.class,
TestDatabaseAutoConfiguration.class,
TestEntityManagerAutoConfiguration.class })
public class TestJpaConfiguration {}
and
#Configuration
#OverrideAutoConfiguration(enabled = false)
#ImportAutoConfiguration(value = {
RepositoryRestMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
WebMvcAutoConfiguration.class,
MockMvcAutoConfiguration.class,
MockMvcSecurityAutoConfiguration.class
})
public class TestRestConfiguration {}
so the TL;DR summary is: use #ContextConfiguration to specify the configuration files that specify #OverrideAutoConfiguration and #ImportAutoConfiguration

How to write a spring-boot application integration test?

I have a spring-boot application with several #RestControllers. Now I want to write an #IntegrationTest to test my application.
I have:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebIntegrationTest("server.port:0")
public class ApplicationTests {
#Test public void someTest() {}
}
this code works fine.
I have splitted my tests in several test classes. One test class per #RestController e.g. TestClass1 and TestClass2.
My question is how do I include those test classes? I am looking for something like the JUnit Suite tests:
#RunWith(Suite.class) and #SuiteClasses({TestClass1.class, ...})
I cannot add another #RunWith to my ApplicationTests class and if I add all these annotations
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebIntegrationTest("server.port:0")
to each of my test classes it causes to start the Tomcat once per test class and this is what I want to avoid. So basically start the Tomcat once and run all tests which are splitted into several test classes.
Thanks

Create global variable in Test Suite accessible by all JUnit Test

I have a question regarding setting up Junit Test Suite. First of all, I am using JUnit libarary version 4.7.
My problem is to create application context in the test suite then allow all the test suite it is running to be accessible to the application context. I need the application context is because some unit test is using it to populate required data. So I am reusing some class to do the deeds.
The following is my snipplet:
#RunWith(Suite.class)
#SuiteClasses({RestServiceUnitTest.class})
public class IntegrationSuite {
public ApplicationContext appCtx;
#BeforeClass
public static void setUp() {
System.out.println("setting up in Suite");
appCtx = new FileSystemXmlApplicationContext("/integrationtest/rest_test_app_ctx.xml" );
}
#AfterClass
public static void tearDown() {
System.out.println("tearing down in Suite");
CleanUp cleaner = (CleanUp)appCtx.getBean("cleanup");
cleaner.clean();
}
}
I need the appCtx to be accessible to the RestServiceUnitTest class. May I know how is this is done ? Anyone has any idea.
I guess it is pretty similiar to :
Test invocation: how to do set up common to all test suites
But I not sure how to access the variable you created in the testsuite class in unittest as the answer is not mentioning it.

Grails integration tests with multiple services

What is the best practice to test a Grails Service which depends on another Service?
The default mixin TestFor correctly inject the service under test, for eg:
#TestFor(TopService)
class TopServiceTests {
#Test
void testMethod() {
service.method()
}
}
but if my instance of TopService (service) relies on another Service, like InnerService:
class TopService {
def innerService
}
innerService will not be available, dependency injection doesn't seem to fill this variable. How should I proceed?
Integration tests should not use the #TestFor annotation, they should extend GroovyTestCase. The test annotations are only for unit tests (and will have bad behavior when used in integration tests, especially the #Mock annotations). You're seeing one of those bad behaviors now.
If you extend GroovyTestCase you can then just have
def topService
At the top of your test and it'll get injected with all of it's dependencies injected.
For a unit test case, you'd just want to add new instances of associated services to your service in a setUp method. Just like:
#TestFor(TopService)
class TopServiceTests {
#Before public void setUp() {
service.otherService = new OtherService()
}
...
I have a CustomerRegistrationServiceTest and my CustomerRegistrationService depends on the PasswordService.
my CustomerRegistrationService just autowires it like normal:
class CustomerRegistrationService {
def passwordService
In my CustomerRegistrationServiceTest I have:
#TestFor(CustomerRegistrationService)
#Mock(Customer)
class CustomerRegistrationServiceTests extends GrailsUnitTestMixin {
void setUp() {
mockService(PasswordService)
}
So when I test the CustomerRegistrationService, it is able to access the PasswordService