How to mock HttpSession in JSF - unit-testing

i have a service method that get session attribute and i want to make unit test for this service method and i was wondering how to mock the HttpSession in jsf.

1- use the FacesContextMocker class:
public abstract class FacesContextMocker extends FacesContext {
private FacesContextMocker() {}
private static final Release RELEASE = new Release();
private static class Release implements Answer<Void> {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
setCurrentInstance(null);
return null;
}
}
public static FacesContext mockFacesContext() {
FacesContext context = Mockito.mock(FacesContext.class);
setCurrentInstance(context);
Mockito.doAnswer(RELEASE).when(context).release();
return context;
}
}
2- in the test class #Before method do the following:
FacesContextMocker.mockFacesContext();
ExternalContext externalContext = Mockito.mock(ExternalContext.class);
Mockito.when(FacesContext.getCurrentInstance().getExternalContext())
.thenReturn(externalContext);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(
FacesContext.getCurrentInstance().getExternalContext()
.getRequest()).thenReturn(request);
HttpSession httpSession = Mockito.mock(HttpSession.class);
Mockito.when(GeneralUtils.getHttpSession()).thenReturn(httpSession);
3- the getHttpSession method is as follows:
public static HttpSession getHttpSession() {
return ((HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getSession();
}
4- in the test method do the following:
Mockito.when(
GeneralUtils.getHttpSession().getAttribute(
"userID")).thenReturn("1");
5- this is assuming that in your service method that you are making the unit test for you have code like:
String currentUserID = (String) GeneralUtils.getHttpSession()
.getAttribute(userID);

Related

“Invalid use of argument matchers” but I use matchers only

I wish to test the following getRights method:
public GetProductRp getRights(String aaId, String bbId, String ccId) {
GetProductRp rp = (GetProductRp) webServiceTemplate.marshalSendAndReceive(createRq(aaId, bbId, ccId));
return rp;
}
private GetProductRq createRq(String aaId, String bbId, String ccId) {
GetProductRq rq = new GetProductRq();
GetProductRqBody body = new GetProductRqBody();
body.setaaId(aaId);
body.setbbId(bbId);
body.setccId(ccId);
rq.setBody(body);
return rq;
}
This is my test class:
#RunWith(SpringRunner.class)
#SpringBootTest()
public class ClassTest {
#Autowired
private Class rightClass;
#MockBean
private WebServiceTemplate webServiceTemplate;
#Test
public void getRightsTest() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
GetProductRp response = Helper.createProductRp("xx", "yy");
Method mCreateRq = rightClass.class.getDeclaredMethod("createRq", String.class, String.class, String.class);
mCreateRq.setAccessible(true);
GetProductRq request = (GetProductRq) mCreateRq.invoke(rightClass, "12345678", "12345678", "1111");
Mockito.when(webServiceTemplate.marshalSendAndReceive(request)).thenReturn(response);
Mockito.when(rightClass.getRights(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(response);
Assert.assertNotNull(response);
}
I receive the error provided in the short description above altough I only use Matchers (Mockito.anyString())....
Any idea?
The issue here could be that you are putting #Autowired on private Class rightClass; and you are trying to mock the method of it. If you want to mock the method then you should put #MockBean annotation as :
#MockBean
private Class rightClass;

Unit testing middleware with NUnit and NSubstitute

I've written a bit of middleware in an ASP.NET Core site and I'm trying to unit test it, mainly by following this guide that uses Moq.
My problem is finding an NUnit/NSubstitute equivalent for new DefaultHttpContext(). Substituting HttpContext will trigger the middleware, but it passes the try. I presume this is because of the issue quoted below. Does NUnit have a function to create a real HttpContext, or am I looking at a lot more infrastructure to achieve this?
I am sending an instance of DefaultHttpContext to the Invoke method. I can't use a mocked HttpContext in this scenario because the first middleware (the lambda function that we passed to the constructor) will need to write to the response. Hence the HttpResponse needs to be a real object not mocked.
Here is the code for my Test
[TestFixture]
public class ExceptionHelperTests
{
private IErrorRepository errorRepository;
private ExceptionHandler handler;
[SetUp]
public void Setup()
{
errorRepository = Substitute.For<IErrorRepository>();
}
[Test]
public async void Given_AnExceptionHappens_Then_ItShouldBeLogged()
{
// Arrange
const string username = "aUser";
var user = Substitute.For<ClaimsPrincipal>();
user.Identity.Name.Returns(username);
handler = new ExceptionHandler(
next: async (innerHttpContext) =>
{
innerHttpContext.User = user;
},
repository: errorRepository);
// Act
await handler.Invoke(new DefaultHttpContext());
// Assert
errorRepository.Received().LogException(Arg.Any<string>(), Arg.Any<Exception>(), Arg.Is(username));
}
}
Here is the IErrorRepository
public interface IErrorRepository
{
Exception LogException(string message, Exception ex, string userId);
void LogMessage(string message, string errorDetail, string userId);
}
And here is the middleware (with a simplified HandleException):
public sealed class ExceptionHandler
{
private readonly RequestDelegate _next;
private readonly IErrorRepository repository;
public ExceptionHandler(RequestDelegate next, IErrorRepository repository)
{
_next = next;
this.repository = repository;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
HandleException(ex, context.User.Identity.Name);
}
}
public void HandleException(Exception ex, string userId)
{
repository.LogException("An unhandled exception has occurred.", ex, userId);
}
}
DefaultHttpContext is just the default implementation of HttpContext abstract class.
You just could do
var HttpContextSub = Substitute.For<HttpContext>();

Integration test for authentication filter with Spring Boot

I would like to implement an integration test to test my authentication filter, implemented with Spring Security, with Spring Boot. But... I am lost...
First, here is my "production" implementation:
I have my web configurer adapter creating an authentication manager and declaring my filter:
#EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
#Autowired
private IdentityService loginService;
#Autowired
private PersonService personService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(loginService).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(PATH_LOGIN).permitAll();
http.authorizeRequests().antMatchers("/**").fullyAuthenticated();
http.addFilterBefore(new AuthenticationFilter(PATH_LOGIN, authenticationManager(), personService),
UsernamePasswordAuthenticationFilter.class);
}
Then, here is my filter implementation:
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private ObjectMapper objectMapper = new ObjectMapper();
private PersonService personService;
protected AuthenticationFilter(String loginPath, AuthenticationManager authenticationManager,
PersonService personService) {
super(loginPath);
this.personService = personService;
setAuthenticationManager(authenticationManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
LoginInfo loginInfo = objectMapper.readValue(request.getInputStream(), LoginInfo.class);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
loginInfo.getUsername(), loginInfo.getPassword());
Authentication authentication = getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
return authentication;
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
Identity identity = (Identity) authResult.getPrincipal();
Person person = personService.getPersonByMail(identity.getUsername());
UserInfo userInfos = new UserInfo();
userInfos.setUser(person);
userInfos.setRoles(identity.getRoles());
objectMapper.writeValue(response.getWriter(), userInfos);
}
}
Now, I have implemented the two services (PersonService & IdentityService) which should be used as mock to prevent any database access:
#Profile("test")
#Service
public class PersonServiceMock implements PersonService {
private static final Map<String, Person> USER_DB;
static {
Person valerian = new Student();
valerian.setMail("valerian#savetheuniverse.com");
USER_DB = new HashMap<>();
USER_DB.put(valerian.getMail(), valerian);
}
#Override
public Person getPersonByMail(String mail) {
return USER_DB.get(mail);
}
}
-
#Profile("test")
#Service
public class IdentityServiceMock implements IdentityService {
private static final Map<String, Identity> USER_DB;
static {
Identity valerian = new Identity("valerian#savetheuniverse.com");
USER_DB = new HashMap<>();
USER_DB.put(valerian.getUsername(), valerian);
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
USER_DB.forEach((key, value) -> {
value.setEnabled(true);
value.setLocked(false);
value.setPassword(encoder.encode("pa$$w0rd"));
});
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails ud = USER_DB.get(username);
return ud;
}
}
In the end, here is my "start of test" I wrote but that does not work because it seems it wants to retrieve the "production" implementation of the service instead of my fake one:
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class AuthenticationTests {
#Autowired
private Filter filterChainProxy;
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).addFilters(filterChainProxy).build();
}
#Test
public void login() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
LoginInfo loginInfo = new LoginInfo("valerian#savetheworld.com", "pa$$w0rd");
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/login")
.content(objectMapper.writeValueAsString(loginInfo));
Person person = new Student("valerian", "none", "valerian#savetheworld.com");
UserInfo expectedUserInfo = new UserInfo(person, null);
String expectedJSonContent = objectMapper.writeValueAsString(expectedUserInfo);
mockMvc.perform(requestBuilder).andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().json(expectedJSonContent));
}
}
Did I misunderstood something? Can you help me, please?
OK. Never mind. It is just that I misunderstood some notion like mocking, faking & stubbing, even if mocking and stubbing are clearly linked in the unit/integration tests.
I modified my code to remove the different interfaces and the "mock" implementation of the services. This type of implementation is more like a "fake-behaviour" implementation than mocking.
In the end, I have this for my test class:
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class AuthenticationTests {
private static final String KNOWN_USER_MAIL = "valerian#mail.com";
private static final String KNOWN_USER_PASSWORD = "pa$$w0rd";
private static Person KNOWN_STUDENT = new Student("valerian", "none", KNOWN_USER_MAIL);
private static Identity KNWON_IDENTITY = new Identity(KNOWN_USER_MAIL);
static {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
KNWON_IDENTITY.setEnabled(true);
KNWON_IDENTITY.setLocked(false);
KNWON_IDENTITY.setPassword(encoder.encode(KNOWN_USER_PASSWORD));
}
#Autowired
// Attribute name very important
private Filter springSecurityFilterChain;
#Autowired
private WebApplicationContext context;
#MockBean // IdentityService automatically mocked when used
private IdentityService identityService;
#MockBean // PersonService automatically mocked when used
private PersonService personService;
private MockMvc mockMvc;
#Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).addFilters(springSecurityFilterChain).build();
// Stub to define the behaviour of the services when they are used
Mockito.when(identityService.loadUserByUsername(KNOWN_USER_MAIL)).thenReturn(KNWON_IDENTITY);
Mockito.when(personService.getPersonByMail(KNOWN_USER_MAIL)).thenReturn(KNOWN_STUDENT);
}
#Test
public void login_success() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
LoginInfo loginInfo = new LoginInfo(KNOWN_USER_MAIL, KNOWN_USER_PASSWORD);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/login")
.content(objectMapper.writeValueAsString(loginInfo));
UserInfo expectedUserInfo = new UserInfo(KNOWN_STUDENT, KNWON_IDENTITY.getRoles());
String expectedJSonContent = objectMapper.writeValueAsString(expectedUserInfo);
mockMvc.perform(requestBuilder).andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().json(expectedJSonContent));
}
}
I am impressed by the magic of the annotation #MockBean and the stubs. :)

JUnit Tests for Liferay MVCPortlet using PowerMock

Im trying to make JUnit Test using PowerMock, but I have one problem. Here is my code:
public class MyGreeting extends MVCPortlet {
public static final String GREETING="greeting";
private static final String DEFAULT_GREETING="MY DEFAULT GREETING MESSAGE";
private static final Log _log = LogFactoryUtil.getLog(MyGreeting.class.getName());
#Override
public void render(RenderRequest req,RenderResponse res)
throws IOException, PortletException {
PortletPreferences prefs = req.getPreferences();
req.setAttribute(GREETING, prefs.getValue(GREETING, DEFAULT_GREETING));
super.render(req,res);
}
And I need to make JUnit test. I created another test package, new MyGreetingTest.java file, and come up to this code:
public class MyGreetingTest extends Mockito{
#BeforeClass
public static void setUpBeforeClass() throws Exception {
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
}
private MyGreeting portlet;
#Before
public void setUp() throws Exception {
portlet = new MyGreeting();
}
#After
public void tearDown() throws Exception {
}
#Mock
public RenderRequest request = mock(RenderRequest.class);
#Mock
PortletPreferences preferences = mock(PortletPreferences.class);
#Test
public final void renderTest() throws IOException, PortletException {
when(request.getPreferences()).thenReturn(preferences);
when(preferences.getValue(MyGreeting.GREETING, null)).thenReturn(value);
portlet.render(request, null);
String result = request.getAttribute(MyGreeting.GREETING).toString();
assertEquals(result, value);
}
But I have NullPointerException, because we can't apply getAttribute method to mock-request. Could you please tell me how to solve this problem? How can I test method with getAttribute method using Mockito?
I think you need to mock your method
Stock stock = mock(Stock.class);
when(stock.getPrice()).thenReturn(100.00); // Mock implementation
when(stock.getValue()).thenCallRealMethod(); // Real implementation

Mocking digest authentication in RestEasy

I am using RestEasy to develop a REST server and using the mock dispatcher (org.jboss.resteasy.mockMockDispatcherFactory) for testing the service in my unit tests. My service requires digest authentication and I would to make that part of my testing.
Each of my services accepts a #Context SecurityContext securityContext parameter.
Is there any way is inject a fake SecurityContext in the dispatcher so that I can test that my security methods function properly?
You have to add the SecurityContext into the context data map in ResteasyProviderFactory.
public class SecurityContextTest {
#Path("/")
public static class Service {
#Context
SecurityContext context;
#GET
public String get(){
return context.getAuthenticationScheme();
}
}
public static class FakeSecurityContext extends ServletSecurityContext {
public FakeSecurityContext() {
super(null);
}
#Override
public String getAuthenticationScheme() {
return "unit-test-scheme";
}
}
#Test
public void securityContextTest() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addSingletonResource(new Service());
ResteasyProviderFactory.getContextDataMap().put(SecurityContext.class, new FakeSecurityContext());
MockHttpRequest request = MockHttpRequest.get("/");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals("unit-test-scheme", response.getContentAsString());
}
}
For those coming across this issue today, adding Contexts has been moved from the RestEasyProviderFactory class into the Dispatcher class using getDefaultContextObjects() method.
I've edited the old answer with the new call:
public class SecurityContextTest {
#Path("/")
public static class Service {
#Context
SecurityContext context;
#GET
public String get(){
return context.getAuthenticationScheme();
}
}
public static class FakeSecurityContext extends ServletSecurityContext {
public FakeSecurityContext() {
super(null);
}
#Override
public String getAuthenticationScheme() {
return "unit-test-scheme";
}
}
#Test
public void securityContextTest() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addSingletonResource(new Service());
dispatcher.getDefaultContextObjects().put(SecurityContext.class, new FakeSecurityContext());
MockHttpRequest request = MockHttpRequest.get("/");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals("unit-test-scheme", response.getContentAsString());
}
}