Allow all actions for authentication in integration test cakephp - unit-testing

I'm currently trying to write an integration test for some controller whereby it is necessary to send an authentication header. In my controller I have some actions made public accessible through the following code:
namespace App\Controller\Api;
use Cake\Event\Event;
use Cake\Network\Exception\UnauthorizedException;
use Cake\Utility\Security;
use Firebase\JWT\JWT;
class UsersController extends AppController
{
public function initialize()
{
parent::initialize();
$this->Auth->allow(['add', 'token']); // public methods
}
.....
}
Now I have an integration test case in which I want to allow that all actions are possible to access without authentication. Is there any simple way to make this possible?
Integration case code:
namespace App\Test\TestCase\Controller;
use App\Controller\Api\UsersController;
use Cake\TestSuite\IntegrationTestCase;
class ApiPicturesControllerTest extends IntegrationTestCase{
public $fixtures = [
'app.albums',
'app.pictures',
'app.users',
'app.comments',
'app.users_albums'
];
public function setUp(){
parent::setUp();
// Allow all actions
// $this->Auth->allow();
}
public function testViewShouldPass(){
$this->configRequest([
'headers' => [
'Accept' => 'application/json'
]
]);
$data = $this->get('/api/pictures/1.json');
$this->assertResponseOk();
}
}

Generally it's possible to manipulate the controller in an overriden \Cake\TestSuite\IntegrationTestCase::controllerSpy() method, like
public function controllerSpy($event)
{
parent::controllerSpy($event);
if (isset($this->_controller)) {
$this->_controller->Auth->allow();
}
}
but as already mentioned in the comments, it would be better to properly authenticate your requests instead!
While integration tests do not necessarily have to be black-box tests, peering into the internals of the test subject isn't an overly good idea. Mocking certain parts in an integration test might be reasonable when you are looking for something in between "test everything" and "test units", ie larger groups of modules, but that should mostly only be necessary when heavy complexity is involved in a request.
See also
API > \Cake\TestSuite\IntegrationTestCase::controllerSpy()
API > \Cake\TestSuite\IntegrationTestCase::$_controller

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

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

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

ServiceStack: Authenticate each request using headers in the HTTP request

I have have read other posts on the same topic, but I haven't really gotten a clear picture of how to best solve this:
I have a webservice, that is "stateless" when it comes to the authentication/session, meaning that the client will send two strings with every request (in the HTTP header), AuthToken and DeviceUUID.
These two strings are then compared to the storage, and if found, we know which user it is.
1)
Id like to use the [Authenticate] attribute for each service that I want to protect, and then a method should be executed where I check the two strings.
2)
If I add the [RequiredRole], a method should also be executed, where I have access to the HTTP headers (the two strings), so I can do my lookup.
I am unsure of how to do this in the easiest and cleanest manner possible. I do not want to create ServiceStack Session objects etc, I just want a method that, for each decorated services, runs a method to check authenticated state.
If you want to execute something else in addition when the [Authenticate] and [RequiredRole] attributes are used then it sounds like you want a custom [MyAuthenticate] Request Filter attribute which does both, i.e. validates that the request is Authenticated and executes your custom functionality, e.g:
public class MyAuthenticateAttribute : AuthenticateAttribute
{
public override async Task ExecuteAsync(IRequest req, IResponse res, object dto)
{
await base.ExecuteAsync(req, res, requestDto);
var authenticated = !res.IsClosed;
if (authenticated)
{
//...
}
}
}
Then use it instead of [Authenticate] in places where you need that extra functionality:
[MyAuthenticate]
public class MyServices { ... }
But I'd personally keep the logic in the attributes separated:
public class MyLogicPostAuthAttribute : RequestFilterAsyncAttribute
{
public override async Task ExecuteAsync(IRequest req, IResponse res, object dto)
{
//...
}
}
So they're explicit and can be layered independently of the [Authenticate] attribute, e.g:
[Authenticate]
[MyLogicPostAuth]
public class MyServices { ... }
Which can also be combined like:
[Authenticate, MyLogicPostAuth]
public class MyServices { ... }

Make that one rest api does not need any logging

There is a Spring Security configuration in my application, so all the rest interfaces need to pass some filters and authentication.
This is the security configuration I have:
#Configuration
#EnableWebSecurity
public class MyProgramSecurityConfiguration extends WebSecurityConfigurerAdapter {
....
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.addFilterBefore(restBasedAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
.and()
.logout().permitAll(false)
.addLogoutHandler(logoutHandler).logoutRequestMatcher(new AntPathRequestMatcher(LOGIN_PATH, HttpMethod.DELETE.toString()))
.logoutSuccessHandler(getLogoutSuccessHandler())
.and()
.sessionManagement().maximumSessions(5);
http.addFilterAfter(termsAndConditionsFilter, TermAndConditionFilter.class);
http.addFilterAfter(certificateValidationFilter, TermsAndConditionsFilter.class);
... // some other filters
}
....
}
But, as I described in the title of the question, I would like to have one endpoint /internal/application/info that can be called by anyone without any need of authentication, logging or whatever. I think that you can do it with regexMatcher, am I right?
I think you should to add one more method of HttpSecurity class, something like that:
....
.and()
.authorizeRequests()
.antMatchers("/internal/application/info")
.permitAll()
....