Reputation: 6459
I am trying to write a unit test for a static method which takes a class and method name and does some reflection to call the method with arguments and store the results. I'm using spring-boot
.
My test actually works when I run the full suite, but when I run the test as standalone it fails. The problem is that I've created a mock class (a hand written mock, not using mockito
or easymock
) which I want the static method to use. However, the reflection can not detect my mock class because the class has not been loaded into the applicationContext
by spring-boot
. Here is the line that fails:
T proxy = SpringApplicationContext.getBean(clazz);
SpringApplicationContext definition:
@Component
public class SpringApplicationContext implements ApplicationContextAware
{
private static ApplicationContext applicationContext_;
@Override
public void setApplicationContext(ApplicationContext applicaitonContext) throws BeansException {
applicationContext_=applicaitonContext;
}
public static <T> T getBean(Class<T> requiredType) throws beanException {
return applicationContext_.getBean(requiredType);
}
*note, I had to retype by hand, please assume obvious syntax errors are typos.
so basically my applicationContext
is not being set or defined. I only need one mock bean in the applicationContext
, I could do it by hand, but is there a more spring
approach using annotations?
Upvotes: 3
Views: 3365
Reputation: 6459
It turns out that my test didn't work rather the were run stand alone or part of a suite, I had a separate issue with using the wrong annotations for @BeforeTest which masked the defect when running the whole suite.
The fix was pretty simple. I added the SpringApplicationConfiguration annotation above my test:
@SpringApplicationConfiguration(classes =
{
MockController.class,
SpringApplicationContext.class
}
public class MyTest extends AstractTestNGSpringContextTests
There are two parts to this. The @SpringApplicationCOnfiguration loads only those values I listed. I could have pointed to configuration classes, but that would ultimately load most of the beans in my enviroment which is overkill for a unit test. So I load the two @component objects needed in my ApplicationContext for my unit test to work only.
I also had to extend AbstractTestNGSpringContextTests because It's the only way to get spring to play nice with the TestNG kit were using for our tests. If others are using junit tests instead of TestNG don't extend the AbstracTestNGSpringContextTests, instead I believe your want to add the annotation:
@RunWith(SpringJUnit4ClassRunner.class)
Though I haven't used it since I'm not using junit.
Hopefully this answer saves others who are trying to figure out how to load only a few classes instead of the entire enviroment (most examples I found want you to load configuration files that will load every bean, which is slow and honestly undesirable in a unit test).
Arguably I should still have mocked out the SpringApplicationContext entirely, I'm lazy and sloppy :)
Upvotes: 2