I have such Application
class:
@Configuration
@EnableAutoConfiguration
@ComponentScan
@ImportResource("classpath:applicationContext.xml")
@EnableJpaRepositories("ibd.jpa")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I also have UserService
class (it is discovered by @EnableJpaRepositories("ibd.jpa")
):
@RestController
@RequestMapping("/user")
public class UserService {
@Autowired
private UserRepository userRepository;
@RequestMapping(method = RequestMethod.POST)
public User createUser(@RequestParam String login, @RequestParam String password){
return userRepository.save(new User(login,password));
}
And I try to test UserService
:
@ContextConfiguration
class UserServiceTest extends Specification {
@Autowired
def UserService userService
def "if User not exists 404 status in response sent and corresponding message shown"() {
when: 'rest account url is hit'
MockMvc mockMvc = standaloneSetup(userService).build()
def response = mockMvc.perform(get('/user?login=wrongusername&password=wrongPassword')).andReturn().response
then:
response.status == NOT_FOUND.value()
response.errorMessage == "Login or password is not correct"
}
But the issue is: UserService in test is null - doesn't wired. Means that Context isn't loaded. Please tell me where the problem in ContextConfiguration of test.
@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests.
The main difference between Spock and JUnit is in breadth of capabilities. Both frameworks can be used for unit testing. However, Spock offers much more — including mocking and integration testing. JUnit requires a third party library for mocking.
Spock ignores bean that is not a singleton (in the singleton scope) by default. To enable mocks to work for scoped beans you need to add @ScanScopedBeans to the spec and make sure that the scope allows access to the bean during the setup phase.
@ContextConfiguration loads an ApplicationContext for Spring integration test. @ContextConfiguration can load ApplicationContext using XML resource or the JavaConfig annotated with @Configuration . The @ContextConfiguration annotation can also load a component annotated with @Component , @Service , @Repository etc.
Was solved by:
@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = Application.class)
@WebAppConfiguration
@IntegrationTest
and usage of RestTemplate
as in this question
Expanding on this since the bounty wanted some elaboration: Spring doesn't wire up beans by default in unit tests. That's why those annotations are needed. I'll try to break them down a little bit:
- Uses SpringBootContextLoader as the default ContextLoader when no specific @ContextConfiguration(loader=...) is defined.
- Automatically searches for a @SpringBootConfiguration when nested @Configuration is not used, and no explicit classes are specified.
Without these annotations, Spring doesn't wire up the beans necessary for your test configuration. This is partially for performance reasons (most tests don't need the context configured).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With