Unit testing controllers with annotations
I'm trying to write some unit tests for my controllers in a Spring MVC web app. I have already got a fairly comprehensive set of unit tests for the domain model, but for completeness I want to test the controllers too.
The issue I'm facing is trying to test them without loading a Spring context. I thought I could get around this with mocking, but the method in the controller has a @Transactional annotation which attempts to open a transaction (and fails with a NullPointerException because no Spring context is loaded).
Code example:
public class UsersController {
@Autowired private UserManager userManager;
@Transactional
@RequestMapping(method = RequestMethod.POST)
public ModelAndView create(User user) {
userManager.save(user);
ModalAndView mav = new ModelAnd开发者_JAVA技巧View();
mav.addObject("user", user);
mav.setViewName("users/view");
return mav;
}
}
So essentially I want to test the behaviour without loading a context and actually persisting the user.
Does anyone have any ideas on how I can achieve this?
Cheers,
Caps
I'd say mocking is the way to go here. The @Transactional
annotation will have no effect unless there is a Spring context loaded and instructed to configure annotation-based transactions.
Make sure that you aren't instructing JUnit to run your test within a spring context by specifying something like:
@ContextConfiguration(locations = "classpath:spring/ITestAssembly.xml")
@RunWith(SpringJUnit4ClassRunner.class)
To prevent confusion, I keep my unit tests (not running in a spring context) in separate files than my integration tests. Typically all mocking occurs in the unit tests and not in integration tests.
The NullPointerException
occurs not because of the Transactional
, but because nothing gets injectedas UserManager
. You have two options:
- run with the spring test runner
- mock the
userManager
and set it.
精彩评论