Creating two instances of SimpleJdbcCall in Guice Service Module - jetty

I am using postgreSql stored procedures for performing changes to database and connecting to it using SimpleJdbcCall. Now i need to create several instances of it based on procedure I am calling.
My Launcher file Service Module has following methods :
#Provides
#Inject
#Named("jdbcTemplate")
JdbcTemplate provideJDBCClient(){return new JdbcTemplate()}
#Provides
#Inject
#Named("aTypeSimpleJdbcCall")
SimpleJdbcCall getSimpleJdbcCallForTypeA(#Named("jdbcTemplate")) {
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate);
simpleJdbcCall.setSchema("some");
simpleJdbcCall.setProcedureName("someName");
return simpleJdbcCall;
}
#Provides
#Inject
#Named("bTypeSimpleJdbcCall")
SimpleJdbcCall getSimpleJdbcCallForTypeB(#Named("jdbcTemplate")) {
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate);
simpleJdbcCall.setSchema("some");
simpleJdbcCall.setProcedureName("someOtherName");
return simpleJdbcCall;
}
Now in class where I need these objects to call excecute method, I am referring these objects like this :
#Inject
#Named("aTypeSimpleJdbcCall")
private SimpleJdbcCall simpleJdbcCallForTypeA;
#Inject
#Named("bTypeSimpleJdbcCall")
private SimpleJdbcCall simpleJdbcCallForTypeB;
#Inject
private JdbcTemplate jdbcTemplate;
I am getting these objects properly as expected and my services are working fine.
What is better way of doing this ?

Related

Unit test - Mocking Service and Repository/Unit Of Work Layer

In my current implementation I use the Domain Service layer to inject the repositories through Unit Of work.
In some cases, I inject other Services into my Service.
However, I have found difficulties to Mock these objects when making unit tests, because whenever a Service class has injection of dependencies with other Services I need to mock the dependencies of that other service.
How to make it work in a simple way?
Was I using the layers wrongly?
Eg:
public class ValueService : IValueService
{
private readonly ITestService _testService;
private readonly IOptionService _optionService;
public ValueService (IUnitOfWork unitOfWork,
ITestService testService,
IOptionService optionService) : base(unitOfWork)
{
_testService = testService;
_optionService = optionService;
}
When I'm going to mock the ValueService class, I need to mock the TestService and OptionService together with their dependencies.
Can you help me to think about this architecture that I'm implementing?
You can try the code below. I hope it helps.
You can inject all your services and repositories.
public class ValueServiceTest
{
private readonly IValueService _valueService;
public ValueServiceTest()
{
_valueService = GetService();
}
***********************
Your test methods.
***********************
private ValueService GetService()
{
var services = new ServiceCollection();
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped<IValueService, ValueService>();
services.AddScoped<ITestService, TestService>();
services.AddScoped<IOptionService , OptionService >();
**********************************
You can inject repositories here.
**********************************
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetService<IValueService>();
}
}

How to write a Unitest case for the apache camel routing in the springboot application

I have been assigned to write unit tests for the Springboot application uses Apache Camel for routing.
Below is a simple routing class.
#Component
public class MyRouteBuilder extends RouteBuilder
{
#Override
public void configure() throws Exception {
super.configure();
from("direct:encrypt").bean(ProcessData.class, "process(${exchange})").end();
}
}
How to write a Unit test for this. The application uses Mockito for writing the testcases for other part of the application.
Please help. Thanks.
Have a look at the documentation about Camel and SpringBoot. There is a section about Testing with JUnit 4 and 5.
Here is an example for Camel 3, SpringBoot 2 and JUnit 5
#CamelSpringBootTest
#SpringBootTest
class MyRouteTest {
#Autowired
private CamelContext camelContext;
#Autowired
private ProducerTemplate producer;
private MockEndpoint mockEndpoint;
#BeforeEach
public void doBeforeEveryTest() {
MockEndpoint.resetMocks(camelContext);
}
#Test
void testWhateverRouteDetail() throws Exception {
mockEndpoint = camelContext.getEndpoint("mock:output", MockEndpoint.class);
mockEndpoint.expectedBodiesReceivedInAnyOrder(yourExpectedBody);
producer.sendBodyAndHeader("direct:encrypt", myBodyContent, headerName, headerValue);
mockEndpoint.assertIsSatisfied();
}
}

Spring Boot 2 MockMVC unit testing with RequestPart and MultipartFile

I have the below email controller for sending email with RequestPart DTO object (userDTO) and Multipart file (3 files upload max). where userDTO is a JSON object
I tried using postman and it works perfectly for sending email with attachments, however i need to develop unit testing using MockMVC and I am not able to find any suitable examples on these combinations of Multipart and Request Part. When i tried using the below test class, i'm not able to hit my controller which will trigger email.
My Controller
#PostMapping(path = "/api/email/sendEmail)
public ResponseEntity<UserDto> sendEmail(#RequestPart(value = "file", required = false) MultipartFile[] uploadfile,
#RequestPart UserDto userDTO, WebRequest webRequest) {
webRequest.setAttribute("userDTO", userDTO, RequestAttributes.SCOPE_REQUEST);
UserDto obj = emailService.sendEmail(userDTO, uploadfile);
return new ResponseEntity<>(obj, HttpStatus.OK);
}
My JSON (userDTO) which comes in request part
{
"sender":"sender#gmail.com",
"recipients":"receiver#gmail.com",
"subject":"Hi Testing Mail API",
"content":"This is my email"
}
My Test Class
#ContextConfiguration
#WebAppConfiguration
public class ServicesApplicationTests {
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#Test
public void testEmail() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
mockMvc.perform(post("/api/email/sendEmail")
.contentType(MediaType.APPLICATION_JSON)
.content("{ \"sender\":\"sender#gmail.com\",\"recipients\":\"receiver#gmail.com\",\"subject\":\"Hi Testing Mail API\",\"content\":\"This is my email\"}")
.accept(MediaType.APPLICATION_JSON));
}
Any leads would be much appreciated. Thanks

PowerMock mock injected Authentication

i am using PowerMockRunner in a spring-boot application for testing. Everything is working but when my controllers actions definition contain someControllerMethod(..., Authentication auth, ...). Then auth is null and therefore some code is not working.
What i tried is to mock Authentication and SecurityContext. Came up with something like this
private void mockSecurity() {
Authentication authentication = mock(Authentication.class);
SecurityContext securityContext = mock(SecurityContext.class);
List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority("USER"));
User mockedUser = new User("testuser", "passwordtest", authorities);
when(securityContext.getAuthentication()).thenReturn(authentication);
SecurityContextHolder.setContext(securityContext);
when(SecurityContextHolder.getContext().getAuthentication().getDetails()).thenReturn(mockedUser);
when(SecurityContextHolder.getContext().getAuthentication().getName()).thenReturn(mockedUser.getUsername());
}
Now those mocks work, if my code uses SecurityContextHolder.getContext().getAuthentication() method of accessing the authentication, but not for the one automatically injected (probably because it is not yet mocked when the controller mock is created).
Any ideas how to mock the injected Authentication so the code does not need to be changed? spring-security-testand #MockWithUser have the same result.
Relevant parts of the test look like this,
#RunWith(PowerMockRunner.class)
public class UserControllerTest {
#InjectMocks
UserController userController;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mockMvc = standaloneSetup(userController).build();
}
#Test
public void getUserDetails() {
mockSecurity();
mockMvc.perform(...).andExpect(...);
}
}
Edit as requested by pvpkiran the controller code
#RequestMapping(...)
public void getDetails(#PathVariable String id, Authentication auth) {
UserDetails loadedDetails = userService.getUserDetails(id);
if (!loadedDetails.getUserId().equals(auth.getName())) {
throw new Exception(...);
}
...
}

How to use Spring Autowired in a custom cxf interceptor?

i seem to run into a small issue when using #Autowired into a custom cxf interceptor.
My use case is that i want to log soap messages and send these using AMQP to another system. This process works for normal services etc.
But whatever i do, the needed properties do not get autowired and stay null.
I checked the Spring DI log and the context is scanned and pickedup, so what am i missing?
Is this even possible in CXF interceptors?
#Component
public class LogInInterceptor extends AbstractSoapInterceptor {
private #Value("#{rabbitMQProperties['rabbitmq.binding.log.soap']}")
String binding;
#Autowired
AmqpTemplate amqpTemplate;
public LogInInterceptor() {
super(Phase.RECEIVE);
}
#Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
logIt(soapMessage);
}
private void logIt(SoapMessage message) throws Fault {
// rest of the code omitted...!!!
amqpTemplate.convertAndSend(binding, buffer.toString());
}
}
You can't mix #InInterceptors (a CXF annotation) and #Component (a Spring annotation). That will create two separate instances of your interceptor: the one whose dependencies are getting injected by Spring, and one created by CXF. (You are providing class names in the #InInterceptors annotation, not a bean ID, so CXF has no way of knowing that you already created an instance in the Spring context.)
Remove the #InInterceptors annotation and, in addition to the component scan:
<context:component-scan base-package="org.example.config"/>
You also need something like this in your application context:
<jaxws:endpoint id="myWebService" address="/MyWebService">
<jaxws:inInterceptors>
<ref bean="myInInterceptor" />
</jaxws:inInterceptors>
</jaxws:endpoint>
I know this is an old question, but Jonathan W's answer helped me and I would like to add to it.
This is how I got custom interceptors and #Autowired to work with Spring Boot 1.3.1:
http://cxf.apache.org/docs/jax-ws-configuration.html
import java.util.Arrays;
import javax.jws.WebService;
import org.apache.cxf.Bus;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
#Configuration
#EnableAutoConfiguration
#ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
public class Application extends SpringBootServletInitializer {
#Autowired
private ApplicationContext applicationContext;
#Autowired
private MyInterceptor myInterceptor;
#Autowired
private HelloWorldImpl helloWorldImpl;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
// Replaces the need for web.xml
#Bean
public ServletRegistrationBean servletRegistrationBean(ApplicationContext context) {
return new ServletRegistrationBean(new CXFServlet(), "/api/*");
}
// Replaces cxf-servlet.xml
#Bean
// <jaxws:endpoint id="helloWorld" implementor="demo.spring.service.HelloWorldImpl" address="/HelloWorld"/>
public EndpointImpl helloService() {
Bus bus = (Bus) applicationContext.getBean(Bus.DEFAULT_BUS_ID);
EndpointImpl endpoint = new EndpointImpl(bus, helloWorldImpl);
// Set interceptors here
endpoint.setInInterceptors(Arrays.asList(myInterceptor));
endpoint.publish("/hello");
return endpoint;
}
// Used when deploying to a standalone servlet container, i.e. tomcat
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
// Web service endpoint
#WebService(endpointInterface = "demo.spring.service.HelloWorld")
//#InInterceptors not defined here
public static class HelloWorldImpl {
}
public static class MyInterceptor extends LoggingInInterceptor {
// #Autowired works here
}
}