Google Guice with Junit and Mockito - java

how can i inject EntityManager(jpa) with Mockito?
I wanna bind Mockito.spy(UserService.class) to guice injector.
but UserService.class has EntityManager for query execution.
When installing 'JunitServiceModule' in guice injector, EntityManager is not found.
See below for error details
com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Error in custom provider, java.lang.NullPointerException
while locating com.google.inject.persist.jpa.JpaPersistService
while locating javax.persistence.EntityManager
My code is below.
(The test code just made the error situation similar.)
(actually 'EntityManager' is located in UserRepository... It's just example!)
(#Transactional is belong to guice)
public class UserServiceTest {
#Inject
private UserService userService;
#Before
public void setUp() {
Injector injector = new TestBuilder().init();
injector.initMembers(this);
Mockito.doReturn(10).when(userService).getEntityCount(UserEntity.class);
}
#Test
public void test() {
assertEquals(10, userService.getEntityCount(UserEntity.class));
}
}
public class TestBuilder {
public TestBuilder() {
}
public Injector init() {
Injector injector = Guice.createInjector(
new TestDBInjectModule("test"),
new JunitServiceModule()
);
}
}
public class TestDBInjectModule extends AbstractModule {
private String unitName;
public TestDBInjectModule(String unitName) {
this.unitName = unitName;
}
#Override
protected void configure() {
install(new JpaPersistModule(unitName));
bind(JpaInitializer.class).asEagerSingleton();
}
#Singleton
private static class JpaInitializer {
#Inject
public JpaInitializer(final PersistService persistService) {
persistService.start();
}
}
}
public class JunitServiceModule extends AbstractModule {
#Override
protected void configure() {
bind(UserService.class).toInstance(Mockito.spy(UserService.class));
}
}
public class UserService {
#Inject
private EntityManager entityManager;
public UserService {} // <-- throw NullPointerException!!! since EntityManager
#Transactional
public void addUser(User user) {
return entityManager.persist(user);
}
public Number getCount() {
return entityManager.createQuery("select count(*) from user", Number.class).getSingleResult();
}
}

Related

How to test CDI injection contains #inject and #any in unit test

I would like to write unit test for this class as below. I have no idea to mock or do any thing to get all implements of interface ConnectDatabase:
#Inject
#Any
private Instance<ConnectDatabase> allConnectType;
public class DAOUtils {
public DAOUtils() {
System.out.println("Constructor...");
}
#Inject
#Any
private Instance<ConnectDatabase> allConnectType;
#PostConstruct
public void init() {
System.out.println("PostConstruct...");
}
#PreDestroy
public void destroy() {
System.out.println("Destroy!");
}
public void query() {
for (ConnectDatabase conn : allConnectType) {
conn.connect();
}
System.out.println("query database...");
}
}
interface:
public interface ConnectDatabase {
public void connect();
}
Does anyone has any ideas? Thank you

Custom AsyncUncaughtExceptionHandler

Using the following configuration for #Async methods :
#Configuration
#EnableAsync
public class AsyncConfig implements AsyncConfigurer {
#Override
public Executor getAsyncExecutor() {
//Just to experiment
return new SimpleAsyncTaskExecutor();
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
}
Is there a way to "get" the ability to autowire (or similar) Services ?
I'd like to use such Services to record errors in database and use common services.
Non working sample :
#Component //seems pointless
public class CustomAsyncExceptionHandler extends ServiceCommons implements AsyncUncaughtExceptionHandler {
protected Logger LOG = LoggerFactory.getLogger(this.getClass());
#Autowired
private MyService myService; //always null
#Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
//null pointer !
myService.doSomething(throwable);
}
}
When using not in #Async methods, #ControllerAdvice global exception handler allows #Autowired fields. Why not in this case ? Is this because of async thread management ?
I just faced this problem and solved this way:
#Configuration
#EnableAsync
public class MyAsyncConfigurer implements AsyncConfigurer {
private CustomAsyncExceptionHandler customAsyncExceptionHandler;
//...
//other code here
//...
#Autowired
public void setCustomAsyncExceptionHandler(CustomAsyncExceptionHandler customAsyncExceptionHandler) {
this.customAsyncExceptionHandler = customAsyncExceptionHandler;
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return this.customAsyncExceptionHandler;
}
}
Custom async exception handler annotated with #Component:
#Component
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
private MyMailService myMailService;
#Autowired
public void setMyMailService(MyMailService myMailService) {
this.myMailService= myMailService;
}
#Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
myMailService.sendMailToAdmin(throwable, method.getName());
}
}
IoC injects both, myMailService and customAsyncExceptionHandler, correctly whith no errors.
I don't think my solution is the most elegant, but tell me what you think. the idea is to bypass the automatic injection mechanism by using ApplicationContextAware interface. My first attempt was to make my AsyncUncaughtExceptionHandler implementing class to also implement ACAware. But that didn't work. Somehow this class, even annotated as Component or Service seems to live a bit outside the Spring environment. So I did this:
#Configuration
#EnableAsync
public class DemoAsyncConfigurer implements AsyncConfigurer, ApplicationContextAware {
private ApplicationContext applicationContext;
And in the same class:
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
DemoAsyncExceptionHandler demoHandler = new DemoAsyncExceptionHandler(); // you can't add the parameter in this constructor, for some reason...
demoHandler.setApplicationContext(applicationContext);
return demoHandler;
}
/**
*
* {#inheritDoc}
*/
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
My DemoAsyncExceptionHandler has the following:
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void handleUncaughtException(Throwable throwable, Method method, Object... params) {
UserService userService = this.applicationContext.getBean("userService", UserService.class);
// call userService method
That worked! Hope I have helped

Rollback All DB Commits in Nested Transactions in Spring

I have the following service layout of nested transactions:
#Component
public class Main implements RPCInterface {
#Autowired
private ServiceA serviceA;
#Autowired
private ServiceB serviceB;
#Autowired
private ServiceC serviceC;
#Override
#Transactional (value="txManager", propagation=Propagation.REQUIRED, rollbackFor={ExceptionOne.class, ExceptionTwo.class, ExceptionThree.class})
public void outerMethod() throws ExceptionO {
try {
serviceA.methodA();
serviceB.methodB();
serviceC.methodC();
} catch (ExceptionOne e) {
throw new ExceptionO(e.getMessage, e);
} catch (ExceptionTwo e) {
throw new ExceptionO(e.getMessage, e);
} catch (ExceptionThree e) {
throw new ExceptionO(e.getMessage, e);
}
}
}
#Service
public class ServiceA implements SA {
#Autowired
private ServiceA1 serviceA1;
#Override
public void methodA() {
serviceA1.methodA1();
}
}
#Service
public class ServiceA1 implements SA1 {
#Autowired
private ServiceDBTable1 serviceDBTable1;
#Autowired
private ServiceA1A serviceA1A;
#Transactional
#Override
public void methodA1() {
serviceDBTable4.callToMapper4();
serviceA1A.methodA1A();
}
}
#Service
#Transactional (value="txManager", propagation=Propagation.REQUIRED)
public class ServiceA1A implements SA1A {
#Autowired
private ServiceDBTable2 serviceDBTable2;
#Override
public void methodA1A() {
serviceDBTable1.callToMapper1();
}
}
#Service
public class ServiceB implements SB {
#Autowired
private ServiceDBTable3 serviceDBTable3;
#Override
#Transactional (value="txManager", propagation=Propagation.REQUIRED)
public void methodB() {
serviceDBTable3.callToMapper3();
}
}
#Service
public class ServiceC implements SC {
#Override
public void methodC() throws ExceptionThree {
// code that throws ExceptionThree
}
}
I need to make all the DB calls within ServiceA and ServiceB nested calls to rollback when ServiceC#methodC() throws an exception (or any of them for that matter that throws an exception -- ServiceA or ServiceB).
I tried to make Main#outerMethod transactional with REQUIRED propagation, but it seems like the database commits are not being rolled back. I have even specified the specific classes with rollbackFor but the commits persist. Does anyone know how to fix this issue?
What I did to make it work was to migrate ServiceB.methodB() and ServiceC.methodC() calls to ServiceA.methodA(), and make methodA() #Transactional while throwing all my exceptions from methodA() and rollback based on those three exceptions (my logic actually allowed me to do that):
#Component
public class Main implements RPCInterface {
#Autowired
private ServiceA serviceA;
#Override
public void outerMethod() throws ExceptionO {
try {
serviceA.methodA();
} catch (ExceptionOne e) {
throw new ExceptionO(e.getMessage, e);
} catch (ExceptionTwo e) {
throw new ExceptionO(e.getMessage, e);
} catch (ExceptionThree e) {
throw new ExceptionO(e.getMessage, e);
}
}
}
#Service
public class ServiceA implements SA {
#Autowired
private ServiceA1 serviceA1;
#Autowired
private ServiceB serviceB;
#Autowired
private ServiceC serviceC;
#Override
#Transactional (value="txManager", propagation=Propagation.REQUIRED, rollbackFor={ExceptionOne.class, ExceptionTwo.class, ExceptionThree.class})
public void methodA() throw ExceptionOne, ExceptionTwo, ExceptionThree {
serviceA1.methodA1();
serviceB.methodB();
serviceC.methodC();
}
}
#Service
public class ServiceA1 implements SA1 {
#Autowired
private ServiceDBTable1 serviceDBTable1;
#Autowired
private ServiceA1A serviceA1A;
#Transactional
#Override
public void methodA1() {
serviceDBTable4.callToMapper4();
serviceA1A.methodA1A();
}
}
#Service
#Transactional (value="txManager", propagation=Propagation.REQUIRED)
public class ServiceA1A implements SA1A {
#Autowired
private ServiceDBTable2 serviceDBTable2;
#Override
public void methodA1A() {
serviceDBTable1.callToMapper1();
}
}
#Service
public class ServiceB implements SB {
#Autowired
private ServiceDBTable3 serviceDBTable3;
#Override
#Transactional (value="txManager", propagation=Propagation.REQUIRED)
public void methodB() {
serviceDBTable3.callToMapper3();
}
}
#Service
public class ServiceC implements SC {
#Override
public void methodC() throws ExceptionThree {
// code that throws ExceptionThree
}
}
Since there is no code presented it is hard to know for sure.
However, transactions only work when methods are public. Private methods are not proxied and hence transaction support for them is not there.
Read through Declarative Transations - Spring Docs for more details.
Please post code if you still are struggling for getting better help.

EJB - Unable to execute results from ServiceLayer

When I execute from DAO layer(ProjectDAOImpl), I'am able to see the results from database.
However when I execute from results from Service layer, I'am getting null pointer exceptions.
java.lang.NullPointerException
ProjectServiceImpl.fetchProjects(ProjectServiceImpl.java:25)
ProjectServiceImpl.main(ProjectServiceImpl.java:36)
How can I resolve this issue?
DAO Layer Interface and Class
#Remote
public interface ProjectDAO {
List<Project> fetchProjectDetail();
}
#Stateless
public class ProjectDAOImpl implements ProjectDAO {
private EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("projects");
public ProjectDAOImpl() {
}
public List<Project> fetchProjectDetail() {
List<Project> listProject = new ArrayList<Project>();
listProject =
getEntityManager().createNamedQuery("Project.findProjects").getResultList();
return listProject;
}
private EntityManager getEntityManager() {
return entityManagerFactory.createEntityManager();
}
}
Service Layer Interface and Class
#Remote
public interface ProjectService {
List<Project> fetchProjectDetail();
}
#Stateless
public class ProjectServiceImpl implements ProjectService {
private ProjectDAO projectDAO;
public ProjectServiceImpl() {
}
#EJB
public void setProjectDAO(ProjectDAO projectDAO) {
this.projectDAO = projectDAO;
}
#GET
#Path("/projects")
#Produces(MediaType.APPLICATION_JSON)
public List<Project> fetchProjects() {
return getProjectDAO().fetchProjectDetail();
}
public ProjectDAO getProjectDAO() {
return projectDAO;
}
public static void main(String [] args) {
ProjectServiceImpl projectServiceImpl = new ProjectServiceImpl();
projectServiceImpl.fetchProjects();
}
}

Why does my my GIN factory always return null?

I am trying to write a Jukito test that uses a GIN factory I created.
My factory looks like so:
public interface ClientFactory {
public DOMModel create(Entity ref);
}
I am binding it in my gin module like so:
public class ClientModule extends AbstractGinModule {
#Override
protected void configure() {
install(new GinFactoryModuleBuilder().build(ClientFactory.class));
}
}
DOMModel looks like so:
public class DOMModel {
...
#Inject
public DOMModel(CollabClientFactory collabFactory, #Assisted Entity ref, #Assisted Document domDoc){
this.colabClient = collabFactory.create("DOMMODEL:"+ref.getID(), "com.server.impl.DOMCollabSite.java", collaborator);
}
...
}
Then my test looks like this:
#RunWith(JukitoRunner.class)
public class Test {
public static class Module extends JukitoModule {
protected void configureTest() {
install(new GinModuleAdapter(new ClientModule()));
}
}
#Inject
ClientFactory modelFactory;
#Test
public void testSimple() throws Exception{
Entity entity = new Entity(){
#Override
public String getID() {
return "someID";
}
};
DOMModel model1 = modelFactory.create(entity);
assertNotNull(model1);
}
}
This test fails because model1 is null, however I get no other errors or warnings whatsoever. What is wrong?

Categories

Resources