Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Context Configuration in spock test

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.

like image 211
Lesya Makhova Avatar asked Jun 15 '15 09:06

Lesya Makhova


People also ask

What is the context configuration used for?

@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests.

Is Spock better than JUnit?

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.

How do you mock a bean in Spock?

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.

Which among the following is used to load the Spring XML configuration for test cases using spring test?

@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.


2 Answers

Was solved by:

@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = Application.class)
@WebAppConfiguration
@IntegrationTest

and usage of RestTemplate

as in this question

like image 128
Lesya Makhova Avatar answered Sep 20 '22 01:09

Lesya Makhova


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:

  • @IntegrationTest (which is now deprecated in favor of @SpringBootTest ) from the docs:
  • 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.
  • @WebAppConfiguration adds the application context, and must be used with...
  • @ContextConfiguration actually determines how to load the "class-level" metadata.

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).

like image 27
Igor Avatar answered Sep 18 '22 01:09

Igor