Java – simulate spring bean
I have the following courses:
public class Plugin { private DistributionManager manager; public void init(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); manager = context.getBean(DistributionManager.class); } public String doSomething(){ String s = manager.doSomething(); return doSomethingElse(s); }
The DistributionManager class itself has many autoconnected dependencies and is marked @ component
Now I want to run some unit tests for all this Code:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"/applicationContext.xml"}) public class PluginTestCase extends AbstractJUnit4SpringContextTests{ @Resource DistributionManager manager; @Test public void testDoSomething(){ Plugin plugin = mock(Plugin.class); //how can I inject DistributionMamanger bean to plugin using mockito? assertEquals("MyResult",plugin.doSomething()); } }
I've never used mockito before Can you help me simulate the plug-in and complete the unit test?
to update:
I try the following tests as suggested:
@RunWith(MockitoJUnitRunner.class) public class PluginTestCase { @Mock DistributionManager manager; @InjectMocks Plugin testedPlugin; @Before public void setUp(){ MockitoAnnotations.initMocks(this); } @Test public void testDao(){ testedPlugin.init(); testedPlugin.doSomething(); } }
However, I have the following exceptions:
org.mockito.exceptions.base.MockitoException: Field 'testedPlugin' annotated with @InjectMocks is null. Please make sure the instance is created *before* MockitoAnnotations.initMocks(); Example of correct usage: class SomeTest { @InjectMocks private Foo foo = new Foo(); @Before public void setUp() { MockitoAnnotations.initMock(this); at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl$1.withBefores(JUnit45AndHigherRunnerImpl.java:27) at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:261) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Solution
If you are a class that you want to unit test, do not simulate the plug-in This is the opposite! In addition, for unit testing, I will definitely avoid creating spring context. Instead, you should only conduct integration testing or some very rare / specific situations
Anyway, I think you want to test the interaction between the plug-in and the manager So you must read the mockito documentation, but this is the first step to inject an emulation manager into the plug-in
@RunWith(MockitoJUinitRunner.class) public class PluginTest { @Mock DistributionManager mockedManager; @InjectMocks Plugin testedPlugin = new Plugin(); // initialization not need when using Mockito 1.9.x @Test public void plugin_should_call_the_the_manager_on_doSomething() { // given // when // then } // other scenarios }
Note that you only need to use JUnit to run the program mockitojuinitrunner Class or utility class and method mockitoannotations Init(), but not both!
Additional comments:
>When you use JUnit 4 X, you don't need to start testing method names by testing, because these are annotated by @ test, and you can name them any readable and expressive test intent you want. > The same applies to setup and removal methods, because they are annotated by @ before and @ anot respectively, and you can describe your setup or removal. > Finally, don't name your test class plugintestcase. The suffix testcase is only used for abstract classes. These abstract classes will be extended through the actual test of the test suffix (such as myclasstest) In any case, Maven surefire will look for a class named * test