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

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

Related

Google Guice with Junit and Mockito

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();
}
}

How can I create different spring beans depending on the input

All the class are implemented from the same interface. What is the best way to create beans depending on the input value we are receiving.
If the value is a it need to invoke one class vs different class if the value is b.
You cloud try something like this:
#Component
public class SomeServiceFactory {
#Autowired
private Someservice someserviceA;
#Autowired
private Someservice someserviceB;
#Autowired
private MyServiceThree SomeserviceC;
public SomeService getSomeService(String serviceType) {
if (serviceType.equals("A")) {
return someserviceA;
} else if (serviceType.equals("B")) {
return someserviceB;
} else {
return someserviceC;
}
}
}
First the interface:
public interface MyService {
void doSomething();
}
Then defining two implementation:
#Service
public class MyServiceA implements MyService {
#Override
public void doSomething() {
// do your business A
}
}
#Service
public class MyServiceB implements MyService {
#Override
public void doSomething() {
// do your business B
}
}
The context:
#Service
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
public class MyServiceContext {
private final Map<String, MyService> strategyMap;
public MyService getMyService(String key) {
// the key is the bean name
return strategyMap.get(key);
}
}
Usage
#Autowired
private MyServiceContext context;
...
// your input key must be the bean name.
context.getMyService(yourInputValue).doSmething();

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.

Mocking a class which uses static void method of another class

public class ProjectIdInitializer {
public static void setProjectId(String projectId) {
//load spring context which i want to escape in my test
}
}
public class MyService {
public Response create(){
...
ProjectIdInitializer.setProjectId("Test");
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({ProjectIdInitializer.class})
public class MyServiceTest{
#InjectMocks
private MyService myServiceMock ;
public void testCreate() {
PowerMockito.mockStatic(ProjectIdInitializer.class);
PowerMockito.doNothing().when(ProjectIdInitializer.class, "setProjectId", Mockito.any(String.class));
// Does not work,still tries to load spring context
Response response=myServiceMock .create();
}
How can i make sure that nothing happens if ProjectIdInitializer.setProjectId() is called from myservice?
As stated in comments, you should be aware that many things might break because of PowerMock.
You need to use PowerMock runner, something like that:
#RunWith(PowerMockRunner.class)
#PrepareForTest(ProjectIdInitializer.class)
public class MyServiceTest{
private MyService myService = new MyService();
public void testCreate()
{
PowerMockito.mockStatic(ProjectIdInitializer.class);
PowerMockito.doNothing().when(ProjectIdInitializer.class, "setProjectId", Mockito.any(String.class));
Response response=myService.create();
}
}
see also this doc.
This self contained sample:
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.ProjectIdInitializer.class)
public class A {
private MyService myService = new MyService();
#Test
public void testCreate() throws Exception {
PowerMockito.mockStatic(ProjectIdInitializer.class);
PowerMockito.doNothing().when(ProjectIdInitializer.class, "setProjectId", Mockito.any(String.class));
System.out.println("Before");
Response response = myService.create();
System.out.println("After");
}
public static class ProjectIdInitializer {
public static void setProjectId(String projectId) {
//load spring context which i want to escape in my test
System.out.println(">>>>>> Game over");
}
}
public static class Response {
}
public static class MyService {
public Response create() {
// ...
ProjectIdInitializer.setProjectId("Test");
return null;
}
}
}
outputs:
Before
After
As expected

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