Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring session with redis - how to mock it in integration tests?

So, Im using spring session in my project. How to write integration tests in project using it? Should I mock something for spring session internals? Or any reasonable way to use embedded redis?

I saw there was some @EnableEmbeddedRedis annotation in past, but seems it was removed: https://github.com/spring-projects/spring-session/issues/248

//edit

Ive tried to pass MockHttpSession to

mockMvc.perform(post("/register").session(mockHttpSession)

but spring tries and fails to connect to redis anyway.

like image 916
hi_my_name_is Avatar asked Oct 08 '15 07:10

hi_my_name_is


People also ask

Can integration tests have mocks?

Integration testing is a must if you want stable software. However, it's difficult to get your integration tests to call the real dependencies, especially when it comes to load tests. That's where API mocking can help. This article will explain you how to do that with maximizing the power of Azure!

What is redis mock?

The goal of the redis-mock project is to create a feature-complete mock of node_redis, which may be used interchangeably when writing unit tests for code that depends on redis . All operations are performed in-memory, so no Redis installation is required.


3 Answers

You can create your own connectionfactory and the redisserializer. Then spring boot won't create their default beans.

Example:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class ApplicationTest
{

    @Test
    public void contextLoads()
    {
    }


    @EnableRedisHttpSession
    @Configuration
    static class Config
    {
        @Bean
        @SuppressWarnings("unchecked")
        public RedisSerializer<Object> defaultRedisSerializer()
        {
            return Mockito.mock(RedisSerializer.class);
        }


        @Bean
        public RedisConnectionFactory connectionFactory()
        {
            RedisConnectionFactory factory = Mockito.mock(RedisConnectionFactory.class);
            RedisConnection connection = Mockito.mock(RedisConnection.class);
            Mockito.when(factory.getConnection()).thenReturn(connection);

            return factory;
        }
    }
}
like image 77
Dmitriy Kosolobov Avatar answered Oct 12 '22 01:10

Dmitriy Kosolobov


ok, ive just disabled redis by using profiles in my integration tests

@ActiveProfiles("integrationtests")
class RegisterControllerTest extends Specification {...

and extracting @EnableRedisHttpSession to its own class:

@Configuration
@EnableRedisHttpSession
@Profile("!integrationtests")
public class RedisConfig {

}

Its more like workaround than solution, but I dont need to test anything inside session anyway.

like image 36
hi_my_name_is Avatar answered Oct 12 '22 01:10

hi_my_name_is


I would not suggest to use mockHttpSession, as it will bypass the integration with spring-session library in the tests. I would

@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
public class ExampleControllerV2SpringSessionTest {

@Autowired
private WebApplicationContext wac;

@Autowired
private SessionRepository sessionRepository;

@Autowired
private SessionRepositoryFilter sessionRepositoryFilter;

//this is needed to test spring-session specific features
private MockMvc mockMvcWithSpringSession;

@Before
public void setup() throws URISyntaxException {

this.mockMvcWithSpringSession = MockMvcBuilders
   .webAppContextSetup(wac)
   .addFilter(sessionRepositoryFilter)
   .build();
}
}

Knowing that it's hard to always have redis instance ready during the test, I would suggest you to use this property spring.session.store-type=hash_map for your test cases.

like image 33
imarchuang Avatar answered Oct 11 '22 23:10

imarchuang