skywalker
skywalker

Reputation: 716

Cannot use custom spring converter in unit test

I am using simple converter for converting string to enum. Here is the custom converter:

@Component
public class SessionStateConverter implements Converter<String, UserSessionState> {

    @Override
    public UserSessionState convert(String source) {
        try {
            return UserSessionState.valueOf(source.toUpperCase());
        } catch (Exception e) {
            LOG.debug(String.format("Invalid UserSessionState value was provided: %s", source), e);

            return null;
        }
    }
}

Currently I am using UserSessionState as PathVariable in my rest controller. The implementation works as expected. However when I try to unit test the rest controller it seems that conversion does not work and it does not hit the controller method.

@RunWith(MockitoJUnitRunner.class)
public class MyTest {
private MockMvc mockMvc;

@Mock
private FormattingConversionService conversionService;

@InjectMocks
private MynController controller;


@Before
public void setup() {
    conversionService.addConverter(new SessionStateConverter());
    mockMvc = MockMvcBuilders.standaloneSetup(controller).setConversionService(conversionService).build();
}


 @Test
public void testSetLoginUserState() throws Exception {
    mockMvc.perform(post("/api/user/login"));
}

}

In debug mode I get following error:

nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'rest.api.UserSessionState': no matching editors or conversion strategy found

In my opinion the mock for conversion service does not work. Any ideas?

Upvotes: 5

Views: 7678

Answers (3)

Borislav Stoilov
Borislav Stoilov

Reputation: 3677

For anyone using SpringBootTest with AutoConfigureMockMvc

@EnableWebMvc
@AutoConfigureMockMvc(addFilters = false)
@SpringBootTest(classes = {MyController.class, MyConverter.class})
class TestController {

  @Autowired
  private FormattingConversionService conversionService;


  @Autowired
  MyConverter myConverter;


  @BeforeEach
  void setUp() {
      conversionService.addConverter(entityConverter);

  }

}

Upvotes: 0

Subin Chalil
Subin Chalil

Reputation: 3660

If anyone uses implements org.springframework.core.convert.converter.Converter<IN,OUT> and if you are getting similar error while using mockMvc, please follow the below method.

@Autowired
  YourConverter yourConverter;

  /** Basic initialisation before unit test fires. */
  @Before
  public void setUp() {
    FormattingConversionService formattingConversionService=new FormattingConversionService();
    formattingConversionService.addConverter(yourConverter); //Here

    MockitoAnnotations.initMocks(this);
    this.mockMvc = MockMvcBuilders.standaloneSetup(getController())
        .setConversionService(formattingConversionService) // Add it to mockito
        .build();
  }

Upvotes: 7

Denis Zavedeev
Denis Zavedeev

Reputation: 8297

The conversionService is a mock.

So this:

conversionService.addConverter(new SessionStateConverter());

calls addConverter on mock. This does nothing useful for you.

I believe you want to use real FormattingConversionService: to do it you need to remove @Mock annotation from conversionService field and use a real instance of FormattingConversionService instead:

private FormattingConversionService conversionService = new FormattingConversionService();

If you need to track invocations on real objects as you would do on mock check out : @Spy

Upvotes: 5

Related Questions