PowerMock mock injected Authentication - unit-testing

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

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

Create a JUnit for Camel route and processor

I am new to JUnit. I am trying to write test case for camel route and processor. I don't know how to start. Here is my route
from("activemq:queue1").process("queueprocessor").toD("activemq:queue2").
I need help to mock my endpoints and processor.
Here mocked all endpoints using "isMockEndpoints" & added expected body content to endpoint(activemq:queue2) and by sending same content as input to mocked endpoint(activemq: queue1) verified assert is satisfied or not.
public class MockEndpointsJUnit4Test extends CamelTestSupport {
#Override
public String isMockEndpoints() {
// override this method and return the pattern for which endpoints to mock.
// use * to indicate all
return "*";
}
#Test
public void testMockAllEndpoints() throws Exception {
// notice we have automatic mocked all endpoints and the name of the endpoints is "mock:uri"
getMockEndpoint("mock:activemq:queue2").expectedMessageCount(1);
getMockEndpoint("mock:activemq:queue2").expectedBodiesReceived("Hello World");
template.sendBody("mock:activemq:queue1", "Hello World");
getMockEndpoint("mock:activemq:queue2").assertIsSatisfied();
/* additional test to ensure correct endpoints in registry */
/* all the endpoints was mocked */
assertNotNull(context.hasEndpoint("mock:activemq:queue1"));
assertNotNull(context.hasEndpoint("mock:activemq:queue2"));
}
}

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

How to mock Response response = ClientBuilder.newClient().target(some url).request().post(Entity.entity(someEntity, MediaType.APPLICATION_JSON))?

I use Jersey client to post request and use Mockito to do unit test. The problem is I don't want to send a real request in the test. I try to mock the whole process like this
when(m_client.target(anyString())).thenReturn(m_webTarget);
when(m_webTarget.request()).thenReturn(m_builder);
when(m_builder.post(Entity.entity(m_Event, MediaType.APPLICATION_JSON))).thenReturn(m_response);
when(m_response.getStatus())
.thenReturn(Response.Status.BAD_REQUEST.getStatusCode());
But how to mock the ClientBuilder?
You can achieve this by using powermock.
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClientBuilder.class)
public class YourTestClass{
//create a mock client here
Client mockClient = Mockito.mock(Client.class);
// use powermockito to mock new call
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(ClientBuilder.class);
PowerMockito.when(ClientBuilder.newClient()).thenReturn(this.mockClient);
//Now you can use mockClient to mock any call using when... then..
}
#Test
public void yourTest() throws Exception {
}
}