I need to run inner class test cases from eclipse using Junit4. I understand that there is org.junit.runners.Enclosed that is intended to serve this purpose. It works well for "plain" unit test i.e. without the need for spring context configuration.
For my case, give sample code below, Adding another annotation of Enclosed does not work since there is a conflict of both SpringJUnit4ClassRunner and Enclosed test runners. How can I solve this problem ?
Note: Kindly ignore any basic spelling mistake/basic import issues in the below example since I tried to cook up from my actual use-case.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/unit-test-context.xml"})
public class FooUnitTest {
// Mocked dependency through spring context
#Inject
protected DependentService dependentService;
public static class FooBasicScenarios extends FooUnitTest{
#Test
public void testCase1 {
.....
List<Data> data = dependentService.getData();
.....
}
}
public static class FooNeagativeScenarios extends FooUnitTest{
#Test
public void testCase1 {
.....
List<Data> data = dependentService.getData();
.....
}
}
}
}
FooUnitTest is a container, you cannot use it as a superclass.
You need to move all your spring-code to Scenario-classes. And use #RunWith(Enclosed.class). For example, with abstract superclass
#RunWith(Enclosed.class)
public class FooUnitTest {
#ContextConfiguration(locations = { "/unit-test-context.xml"})
protected abstract static class BasicTestSuit {
// Mocked dependency through spring context
#Inject
protected DependentService dependentService;
}
#RunWith(SpringJUnit4ClassRunner.class)
public static class FooBasicScenarios extends BasicTestSuit {
#Test
public void testCase1 {
.....
List<Data> data = dependentService.getData();
.....
}
}
#RunWith(SpringJUnit4ClassRunner.class)
public static class FooNeagativeScenarios extends BasicTestSuit {
#Test
public void testCase1 {
.....
List<Data> data = dependentService.getData();
.....
}
}
}
Of course you can declare all dependencies in each Scenario-class, in that case there is no necessary in abstract superclass.
Related
I have an annotated Junit 4 test using JDK 1.8 running in Eclipse. I'm using Mockito to mock the DAO in the service class under test. The runner in the abstract class extends SpringJUnit4ClassRunner. When I run the test, the unimplemented method in the concrete DAO class is called, instead of the mocked method. I've searched and searched, and can't seem to find a solution. What am I doing wrong?
SOLVED - I changed the #InjectMocks #Autowired IOrganizationsService organizationsService; to remove the interface and autowiring, #InjectMocks OrganizationsService organizationsService; fixed below, and the DAO gets mocked. Now the question, why wasn't the DAO in the declaration using the interface mocked?
#ContextConfiguration(classes = { AppXmlConfigTest.class, AppConfig.class }, inheritLocations = false)
#WebAppConfiguration
public class MockOrganizationsServiceTest extends AbstractCoreJunit4Test {
public MockOrganizationsServiceTest() {
super();
}
#InjectMocks
OrganizationsService organizationsService;
#Mock
IOrganizationsDao organizationsDao;
#Before
public void setupMock() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testGetOrganizations() {
LocalDate localDate = LocalDate.now();
List<OrganizationTypeEnum> organizationTypes = new ArrayList<OrganizationTypeEnum>();
organizationTypes.add(OrganizationTypeEnum.All);
List<AllocationStatusEnum> allocationStatuses = new ArrayList<AllocationStatusEnum>();
allocationStatuses.add(AllocationStatusEnum.ALL);
List<IOrganization> organizations = new ArrayList<IOrganization>();
IOrganization organization = new Organization();
organization.setOrganizationId(1);
organizations.add(organization);
Mockito.when(organizationsDao.getOrganizations(isA(LocalDate.class), isA(List.class), isA(List.class))).thenReturn(organizations);
List<IOrganization> orgs = organizationsService.getOrganizations(localDate, organizationTypes, allocationStatuses);
assertNotNull(orgs);
}
}
The service class is this,
public class OrganizationsService extends AbstractService implements IOrganizationsService {
#Autowired
IOrganizationsDao organizationsDao;
/**
* #param organizationsDao the organizationsDao to set
*/
public void setOrganizationsDao(IOrganizationsDao organizationsDao) {
this.organizationsDao = organizationsDao;
}
#Override
public List<IOrganization> getOrganizations(LocalDate effectiveDate, List<OrganizationTypeEnum> organizationTypes, List<AllocationStatusEnum> allocationStatuses) {
return organizationsDao.getOrganizations(effectiveDate, organizationTypes, allocationStatuses);
}
and the DAO is this,
public class OrganizationsDao extends AbstractDao implements IOrganizationsDao {
#Override
public List<IOrganization> getPendingOrganizations(LocalDate effectiveDate) {
// TODO Auto-generated method stub
return null;
}
#Override
public List<IOrganization> getOrganizations(LocalDate effectiveDate, List<OrganizationTypeEnum> organizationTypeEnums,
List<AllocationStatusEnum> allocationStatuses) {
// TODO Auto-generated method stub
return null;
}
I think the issue here is that while mocking the method call you are using isA for parameters. As per my understanding, isA method is used for the verification not for passing the parameters. Try any method instead:
Mockito.when(organizationsDao.getOrganizations(any(LocalDate.class), any(List.class), any(List.class))).thenReturn(organizations);
Guice module integration issue with REST
I have define one AOP guice based module, but when I tried to integrate with REST code, methodInvocation.proceed retun null.
What might be best way to solve this issue.
Define AOP Guice based module as below
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface NotOnWeekends {}
public class WeekendBlocker implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
Calendar today = new GregorianCalendar();
if (today.getDisplayName(DAY_OF_WEEK, LONG, ENGLISH).startsWith("S")) {
throw new IllegalStateException(
invocation.getMethod().getName() + " not allowed on weekends!");
}
return invocation.proceed();
}
}
public class NotOnWeekendsModule extends AbstractModule {
protected void configure() {
bindInterceptor(Matchers.any(), Matchers.annotatedWith(NotOnWeekends.class),
new WeekendBlocker());
}
}
But I tried to Integrate this with my REST API
public class WorkerBean implements Worker {
#Autowired
private WorkerRepository workerRepository;
#Override
#NotOnWeekends
public Collection<Worker> findAll() {
Collection<Worker> workers = workerRepository.findAll();
return workers;
}
#RestController
public class WorkerController {
#RequestMapping(
value = "/api/workers",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Collection<Worker>> getWorkers() {
Worker worker = Guice.createInjector(new NotOnWeekendsModule()).getInstance(Worker.class);
Collection<Worker> worker = worker.findAll(); // return null
....
}
I want to unit test Camel code using ScalaTest and the FunSpec test style.
To do so, I need to extend from both FunSpec and CamelTestSupport. However, both these are classes and at least one needs to be a trait in order to do this in Scala. For example, this does not work:
class MySpec extends FunSpec with CamelTestSupport {}
Note: It appears that many online references to FunSpec suggest it is a trait, but it is a class in scalatest_2.11-3.0.0-M15.
How can I use ScalaTest FunSpec to test Camel?
The same test written using JUnit would look as follows:
public class DataLakeEventListenerRouteIT extends CamelTestSupport {
#Autowired
private MyRouteBuilder myRouteBuilder;
private MockEndpoint myEndpointMock;
#Override
public boolean isUseAdviceWith() {
return true;
}
#Override
protected JndiRegistry createRegistry() throws Exception {
JndiRegistry registry = super.createRegistry();
//do some required bindings here
return registry;
}
#Before
public void startup() throws Exception {
AdviceWithRouteBuilder mock = new AdviceWithRouteBuilder() {
public void configure() throws Exception {
mockEndpointsAndSkip(myRouteBuilder.MY_ROUTE_URI);
}
};
context.addRoutes(myRouteBuilder);
context.getRouteDefinition(myRouteBuilder.MY_ROUTE_ID)
.adviceWith(context, mock);
myEndpointMock = getMockEndpoint(
"mock:" + myRouteBuilder.MY_ROUTE_URI);
}
#Test
public void timerRouteShouldSendMessage() throws Exception {
// Arrange
context.start();
myEndpointMock.expectedMessageCount(1);
myEndpointMock.assertIsSatisfied();
context.stop();
}
}
Well, it turns out to straightforward. ScalaTest offers a trait equivalent of FunSpec called FunSpecLike. Declare the test like so:
class StoreSVSFileRouteSpec extends CamelTestSupport with FunSpecLike {}
Here is the unit testing code. When we run unit test code (SampleServiceTest2); EntityManager injected in AbstractDao is always null! How can we inject em during unit test.
*** SampleServiceTest2.java
import javax.inject.Inject;
import org.jglue.cdiunit.CdiRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
#RunWith(CdiRunner.class)
public class SampleServiceTest2 {
#Inject SampleService greeter;
#Test
public void testGreeter() throws Exception {
System.out.println("before2");
greeter.addSampleData(new SampleDataDto(), new KullaniciDto());
System.out.println("after2");
}
}
*** SampleService.java
import javax.ejb.Stateless;
import javax.inject.Inject;
....
#Stateless
#SecuredBean
public class SampleService {
#Inject
SampleLogic sampleLogic;
#Yetki(tag="perm_add_sample_data")
public void addSampleData(SampleDataDto data, KullaniciDto aktifKullaniciDto){
SampleDataHelper sampleDataHelper = new SampleDataHelper();
SampleData sampleData = sampleDataHelper.getEntity(data);
KullaniciHelper kullaniciHelper = new KullaniciHelper();
Kullanici kullanici = kullaniciHelper.getEntity(aktifKullaniciDto);
sampleLogic.addData(sampleData, kullanici);
}
}
**** SampleLogic.java
import javax.inject.Inject;
....
public class SampleLogic {
#Inject
SampleDataDao sampleDataDao;
public void addData(SampleData data, Kullanici kullanici) {
addData1(data,kullanici);
System.out.println("SampleLogic : addData() called!");
}
public void addData1(SampleData data, Kullanici kullanici) {
sampleDataDao.create(data, kullanici);
}
}
**** SampleDataDao.java
public class SampleDataDao extends AbstractDao<SampleData> {
private static final long serialVersionUID = 1L;
}
**** AbstractDao.java
public abstract class AbstractDao<T extends BaseEntity> implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName="meopdb")
private EntityManager em;
protected EntityManager getEm() {
return em;
}
#SuppressWarnings("rawtypes")
private Class entityClass;
#SuppressWarnings("rawtypes")
private Class getEntityClass() {
if (entityClass == null) {
entityClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
return entityClass;
}
public T create(T t, Kullanici kullanici) {
if (t.getId() != null) {
throw new IllegalStateException("Create Operation: Oid should be null");
}
t.setId(getSeqNextValue(t));
t.setEklemeZamani(new Timestamp(Calendar.getInstance().getTimeInMillis()));
t.setEkleyenKullaniciId(kullanici.getId());
t.setDurumId(EnumDurum.AKTIF.getValue());
t = em.merge(t);
em.flush();
return t;
}
}
If you test with CDIUnit, the only thing you get is CDI injections, not the full power of Java EE. Injecting entityManager using #PersistenceContext into AbstractDAO is not part of standalone CDI, it is only supported when application is running within a Java EE application server.
The solution is to inject EntityManager using CDI mechanism and create a producer. The producer could be then switched for an alternative in unit tests to provide test entityManager. However, setting up JPA in a standalone unit test is not so straightforward, as you need to specify connection properties directly in persistence.xml file. Also, do not forget to add dependencies on a JPA implementation (hibernate, eclipselink) into your test dependencies.
However, if you do not want to adapt your application's code or you need more than CDI in your tests, you should have a look at Arquillian Java EE test framework.
Here is an example for CDIUnit:
public abstract class AbstractDao<T extends BaseEntity> implements Serializable {
...
#Inject
#Named("meopdb")
private EntityManager em;
...
}
// producer in application - just a wraper over `#PersisteneContext`
public class EntityManagerProducer {
#Produces
#PersistenceContext(unitName="meopdb")
#Named("meopdb")
private EntityManager em;
}
/* producer in your test sources - it creates entityManager via API calls instead of injecting via `#PersistenceContext`. Also, a different persistence unit is used so that it does not clash with main persistence unit, which requires datasource from app server
*/
public TestEntityManagerProducer {
#Produces
#ProducesAlternative // CDIUnit annotation to turn this on as an alternative automatically
#Named("meopdb")
public EntityManager getEm() {
return Persistence
.createEntityManagerFactory("meopdb-test")
.createEntityManager();
}
}
And it is not yet enough. You need to create a new persistence.xml in your test resources with the test persistence unit named "meopdb-test". For this unit you need to specify RESOURCE_LOCAL transaction-type, and specify connection information. And last thing not to forget - you need to list all your entities in the persistence.xml, or in external orm file. This is because your tests run outside of application server. Inside app server, JPA can find entities automatically.
As #OndroMih said, in CDI-Unit, the only thing you get is CDI injections. So you have to cheat a little.
You can use extension do add javax.inject.Inject annnotation to all #PersistenceContext injections
import java.util.Set;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.*;
import javax.inject.Inject;
import javax.persistence.PersistenceContext;
import org.apache.deltaspike.core.util.metadata.AnnotationInstanceProvider;
import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder;
public class AddInjectToPersistenceContextInjectionsCdiExtension implements Extension {
<T> void processAnnotatedType(#Observes ProcessAnnotatedType<T> pat) {
Set<AnnotatedField<? super T>> fields = pat.getAnnotatedType().getFields();
for (AnnotatedField<? super T> field : fields) {
if (shouldInjectionAnnotationBeAddedToField(field)) {
AnnotatedType<T> at = pat.getAnnotatedType();
AnnotatedTypeBuilder<T> builder = new AnnotatedTypeBuilder<T>().readFromType(at);
Inject injectAnnotation = AnnotationInstanceProvider.of(Inject.class);
builder.addToField(field, injectAnnotation);
pat.setAnnotatedType(builder.create());
}
}
}
private <X> boolean shouldInjectionAnnotationBeAddedToField(AnnotatedField<? super X> field) {
return !field.isAnnotationPresent(Inject.class) &&
field.isAnnotationPresent(PersistenceContext.class);
}
}
and produce suitable EntityManager in test class
#RunWith(CdiRunner.class)
#AdditionalClasses(AddInjectToPersistenceContextInjectionsCdiExtension.class)
public class SampleServiceTest2 {
#Inject SampleService greeter;
EntityManagerFactory emf;
#PostConstruct
void init() {
emf = Persistence.createEntityManagerFactory("integration");
}
#Produces
EntityManager createEntityManager() {
return emf.createEntityManager();
}
#Test
public void testGreeter() throws Exception {
}
}
It's not exactly equivalent of what Java EE container does, but it's close enough more often than not.
I have a JUnit test that I run on one class, but I recently wrote an emulated version for GWT. Since the specification is the same, I would like to use the same test case, but I want it to run in the GWT environment, which would typically be accomplished by extending GWTTestCase.
I really want to avoid any copy/paste nonsense, because there are likely to be added tests in the future, which I should not be burdened with copying later.
How can I import/inherit my standard unit test to be run as either a regular test case or a GWT test case?
I have found the solution to this problem.
If you extend the original test with GWTTestCase, you can override getModuleName to return null. This tells GWTTestCase to run as a normal pure java test (no translation at all).
You can then extend this test case with one that overrides getModuleName to return a module name, and the same tests will be run with translation.
Basically:
public class RegularTest extends GWTTestCase {
#Override
public String getModuleName() { return null; }
public void testIt() {...}
}
...and the GWT version...
public class GwtTest extends RegularTest {
#Override
public String getModuleName() { return "some.module"; }
}
The downside to this is that it forces you to use JUnit3 style tests, which I find a little annoying, but it beats the alternative.
I think there is no easy way .. But you can extract an interface of your junit test, gwt test case and junit test case implements this interface. You can create a third class for implementation, all test call methods of gwt test case and junit test are delegated to this implementation class.
public interface IRegularTest {
public void testSomething();
public void testSomething2();
}
public class RegularTestImpl implements IRegularTest {
public void testSomething(){
// actual test code
}
public void testSomething2(){
// actual test code
}
}
public class RegularTest extends TestCase implements IRegularTest {
IRegularTest impl = new RegularTestImpl();
public void testSomething(){
impl.testSomething
}
public void testSomething2(){
}
}
public class GwtTest extends TestCase implements IRegularTest {
IRegularTest impl = new RegularTestImpl();
public void testSomething(){
impl.testSomething
}
public void testSomething2(){
}
}