mockmvc: when I use mockMvc to test a controller, how to deal with the parameter Authentication? - mockito

I am going to test my controller using springsecurity.
#PostMapping("/xx")
public String xx(Authentication auth){
String userId = (String)auth.getPrincipal();
....
}
I have no idea how to mock Authentication object. Or is there other way to deal with it?
My test shown below
public class MyControllerTest{
#Autowired
private XxController xxController;
private MockMvc mockMvc;
#Before
public void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(xxController).build();
}
#Test
public void xxtestMethod() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(/xx))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
}

For basic auth, after trying different ways to do it, I found this worked for me :
MockMvcRequestBuilders
.post(urlEndpoint)
.principal(new MyAuthentication())
Notice that MyAuthentication class implements the Authentication interface

Related

Unable to inject Captor with QuarkusTest

I am trying to write integration tests for Quarkus using Mockito, but I fail using Argument captor.
Here is a minimal (not) working example :
#QuarkusTest
#ExtendWith(MockitoExtension.class)
public class SimpleTest {
#Captor
private ArgumentCaptor<Context> contextArgumentCaptor;
#Test
public void testOne() {
System.out.println(contextArgumentCaptor);
}
}
contextArgumentCaptor is "null".
If I remove #QuarkusTest, contextArgumentCaptor is created.
It also works with #QuarkusTest and direct Argument creator :
#QuarkusTest
public class ConfigTest {
private ArgumentCaptor<Context> contextArgumentCaptor;
#BeforeEach
public void setup() {
contextArgumentCaptor = ArgumentCaptor.forClass(Context.class);
}
#Test
public void givenValidCloudEvent_whenHandleHandoverFunction_ThenHandoverStarted() {
System.out.println(contextArgumentCaptor);
}
}
So it is really the combinaison of #QuarkusTest with #Captor that doesn't work.
Any idea?
Yes, using #QuarkusTest along with the #Captor will not work correctly. You must create the captor yourself

Springboot mockito mock a field

I want to mock the TreeMap in Service class, I tried to mock using TreeMap<String, String> requestsMap = Mockito.mock(TreeMap.class); But the map is getting null at runtime.
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class ServiceTest {
#InjectMocks
private Service service;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
TreeMap<String, String> requestsMap = Mockito.mock(TreeMap.class);
}
}
#Service
public class Service {
private TreeMap<String, String> requestsMap = null;
}
Your Service class doesn't actually do anything but declare and initialize the requestMap to null. Also, your test method doesn't do anything other than declare a mock requestMap.
In addition to the code you have, write a method in the Service that uses the request map and just declare/autowire the requestMap. In your test, use the #Mock annotation on a declaration of your mock requestMap. Finally, use the mocked requestMap in your test.
For example:
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class ServiceTest {
#Mock
TreeMap<String, String> requestsMap;
#InjectMocks
private Service service;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
when(requestMap.get("foo")).thenReturn("bar");
String result = service.doSomething();
assertEquals(result, "bar");
}
}
#Service
public class Service {
#Autowired
private TreeMap<String, String> requestsMap;
public String doSomething() {
return requestMap.get("foo");
}
}

#SpringIntegrationTest annotation does not load context as expected

Normally, when I use #SpringBootTest I get the full context of beans. I can the #Autowire all kinds of beans that are available after the application has started.
Now, in the scope of spring-integration-test libary, the #SpringIntegrationTest does not do this.
As the testing module promises, you can use
#Autowired
private MockIntegrationContext mockIntegrationContext;
However, after inspecting the bean map on that instance, I found out there are no beans!
Example test:
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#SpringIntegrationTest
public class AppTest {
#Autowired
private MockIntegrationContext mockIntegrationContext;
#Test
public void contextLoads() {
// put breakpoint to inspect field
System.out.println(mockIntegrationContext);
}
}
When I however run the following code, I get a complete context:
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#SpringBootTest
public class App2Test {
#Autowired
private ListableBeanFactory beanFactory;
#Test
public void contextLoads() {
Assert.isTrue(beanFactory.getBeanDefinitionCount() > 0)
}
}
Why is that? How can I achieve a similar result with spring-integration-test?
Reading materials: https://docs.spring.io/spring-integration/docs/current/reference/html/testing.html
They are independent annotations; you need both.
EDIT
This works fine for me:
#RunWith(SpringRunner.class)
#SpringBootTest
#SpringIntegrationTest
public class So52297757ApplicationTests {
#Autowired
private MockIntegrationContext mockIntegrationContext;
#Autowired
private String foo;
#Test
public void contextLoads() {
System.out.println(foo);
System.out.println(mockIntegrationContext);
}
}
and
#SpringBootApplication
public class So52297757Application {
public static void main(String[] args) {
SpringApplication.run(So52297757Application.class, args);
}
#Bean
public String foo() {
return "foo";
}
}
and
foo
org.springframework.integration.test.context.MockIntegrationContext#1de5f0ef

Mockito - Testing method that calls private methods

I was trying to find solution but haven't found yet. I tried to test public method which has calls of the couple of private ones inside. One of the problem that private method retrieves Hibernate's Criteria by generic method that in its turn retrieves it through chain of another generic methods. Please take a look at the code below. Frankly I'm not sure that it is possible to test that case but if anyone has ideas please suggest them:
ConcreteDao
public class ConcreteDao extends EntityDao<ConcreteEntity> {
public Class<ConcreteEntity> getClassType() {
return ConcreteEntity.class;
}
}
EntityDao
public abstract class EntityDao<T> extends AbstractDao<T>{
public List<T> getEntityByFilter(EntityFilter filter) {
Criteria criteria = getCriteriaByFilter(filter.getFilters());
criteria.setMaxResult(filter.getMaxResult());
criteria.setFirstResult(filter.getFirstResult());
criteria.addOrder(Order.asc(filter.getSortedField()));
criteria.list();
}
private Criteria getCriteriaByFilter(List<CustFilter> filters) {
Criteria criteria = getCriteria();
for (CustFilter filter : filters) {
filter.addrestrictionToCriteria(criteria, filter.getProperty(), filter.getValue());
}
return criteria;
}
}
AbstractDao
public abstract class AbstractDao<T> {
private EntityManagerFactory entityManagerFactory;
public abstract getClassType();
public Criteria getCriteria() {
return getSession().createCriteria(getClassType());
}
public Session getSession() {
Session session = (Session) getEntityManager().getDelegate();
return session;
}
public EntityManager getEntityManager() {
entityManagerFactory.getEntityManager();
}
}
Test class
#RunWith(MockitoJUnitRunner.class)
public class ConcreteDaoTest {
#Mock
private EntityManager entityManager;
#Mock
private Session session;
#Mock
private Criteria criteria;
private List<CustFilter> filters;
private EntityFilter entityFilter;
private List<ConcreteEntity> resultList;
#InjectMocks
private ConcreteDao concreteDao = new ConcreteDao;
public void init() {
filters = new ArrayLis<CustFilter>();
CustFilter custFilter = new CustFilter();
//fill filter;
filters.add(custFilter);
entityFilter = new EntityFilter();
//fill entityFilter
entityFilter.setFilters(filters);
ConcreteEntity concreteEntity = new ConcreteEntity();
resultList = new ArrayList<ConcreteEntity>();
resultList.add(concreteEntity);
}
#Test
public void getEntityByFilterTest() {
when(concreteDao.getEntityManager).thenReturn(entityManager);
when(concreteDao.getSession()).thenReturn(session);
when(concretedao.getCriteria()).thenReturn(criteria);
when(filter.getFilters()).thenReturn(filters);
when(filter.getMaxResult()).thenReturn(10);
when(filter.getFirstResult()).thenReturn(0);
when(filter.getSortedField()).thenReturn("firstName");
when(criteria.list()).thenReturn(resultList);
List<ConcreteEntity> result = concreteDao.getEntityByFilter(entityFilter);
Assert.assertThen(result. is(notNullValue()));
}
}
With Mockito, you cannot mock private method calls.
Try PowerMockito with which you can mock any kinds of methods like static methods, private methods, local method instantiations and so on.

Custom AuthenticationFilter with token-based authentication

I am using token-based authentication. I have a custom authentication filter which does a REST call to authenticate the user. I managed to create and configure the custom authentication provider but having trouble setting the order of the providers. I want the default DaoAuthenticationProvider to be the default and customProvider to be the secondary.
This is how I configured the customAuthenticationProvider
#Inject
private CustomAuthenticationProvider customAuthenticationProvider;
#Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider)
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
How can I configure customAuthenticationProvider to be the second provider?
PS: I couldn't Inject the customAuthenticationProvider into SecurityConfiguration.java as the Proxy couldn't be created until I added the following scope to customAuthenticationProvider.
#Component("alfrescoAuthenticationProvider")
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")
public class AlfrescoAuthenticationProvider implements AuthenticationProvider {
....
}
I don't understand what you said about why you can not inject. My SecurityConfiguration class is as below:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Inject
private Http401UnauthorizedEntryPoint authenticationEntryPoint;
#Inject
private UserDetailsService userDetailsService;
#Inject
private TokenProvider tokenProvider;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
auth.authenticationProvider(weixinAuthenticationProvider());
}
#Bean
public WeixinAuthenticationProvider weixinAuthenticationProvider() {
WeixinAuthenticationProvider provider = new WeixinAuthenticationProvider(userDetailsService, passwordEncoder());
return provider;
}
#Override
public void configure(WebSecurity web) throws Exception {
......
I hope it can help.

Resources