Regarding Unit Testing of Spring Boot REST Controller, I got a problem with @RequestMapping and application properties.
@RestController
@RequestMapping( "${base.url}" )
public class RESTController {
@RequestMapping( value = "/path/to/{param}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE )
public String getStuff( @PathVariable String param ) {
// implementation of stuff
}
}
I am working with several profiles for the application and therefore I have several application-{profile}.properties
files. In each file the base.url
property value is set and present. I also have a different Spring Context Configuration for testing, which only differs in just one Bean from the productive version.
My Unit Test looks like the following, with using JUNit and Mockito / RestAssured:
@ActiveProfiles( "dev" )
@RunWith( SpringJUnit4ClassRunner.class )
@SpringApplicationConfiguration( classes = SpringContextConfigTest.class )
public class RESTControllerTest {
private static final String SINGLE_INDIVIDUAL_URL = "/query/api/1/individuals/";
@InjectMocks
private RESTController restController;
@Mock
private Server mockedServer; // needed for the REST Controller to forward
@Before
public void setup() {
RestAssuredMockMvc.mockMvc( MockMvcBuilders.standaloneSetup(restController).build() );
MockitoAnnotations.initMocks( this );
}
@Test
public void testGetStuff() throws Exception {
// test the REST Method "getStuff()"
}
Problem is, that the REST Controller is working when started in the production mode. In the unit test mode, the ${base.url}
value is not set and an exception is thrown, when building the mockMvc object:
java.lang.IllegalArgumentException: Could not resolve placeholder 'base.url' in string value "${base.url}"
I also tried it with the following approaches, but with different exceptions:
@IntegrationTest
on Test,@WebAppConfiguration
,- using the
webApplicationContext
to build the MockMVC - autowiring the RESTController in the Test
- defining the REST Controller Bean in the SpringContextConfigTest Class manually
and various other combinations, but nothing seems to work. So how do I have to go on, in order to make it work? I think it's a Context configuration issue with the two different config classes, but I don't know how to solve it or how to do it "right".
It seems that in non-production mode property placeholders can't be resolved. You definitely want to look into PropertyPlaceholderConfigurer documentation page.
This answer could also provide some help with implementation.
I solved the issue with using one
application.yml
file instead of profile-properties. The yml file is using a standard definition for thedefault
profile, which is defined at the top of the file.You will be required to add placeholder value to teh stand alone setup -