2011-11-19 94 views
3

我有以下类:嘲讽的Spring bean

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); 
    } 

DistributionManager类本身有很多自动装配Autowired依赖并标记为@Component

现在我想运行一些单元测试的所有代码:

@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()); 
    } 

} 

我从来没有使用过mockito。你能帮我模拟插件并完成这个单元测试吗?

更新:

我根据建议尝试以下测试:

@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(); 
    } 
} 

,但是,我有以下异常:

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) 
+3

如果你想单元测试'Plugin'类,那你为什么要嘲笑它呢? – skaffman

+0

@scaffman,可能是我错了,我从来没有用过嘲笑。我应该嘲笑什么? –

+0

我不知道,你还没有告诉我们你想要测试什么。您可能想要阅读Mockito主页上的简单教程,以更好地了解您想要实现的目标。 – skaffman

回答

13

不要嘲笑Plugin如果这是你想要单元测试的课程。这是相反的!另外对于单元测试,我肯定会避免创建一个弹簧环境,而应该只为集成测试或一些非常罕见/特定的情况。

无论如何,我想你想测试插件和管理器之间的交互。所以你应该一定要阅读Mockito文档,但这是第一个让插件注入模拟管理器的开始。

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

请注意,您只需要eihter的JUnit运行MockitoJUinitRunner.class或实用类和方法MockitoAnnotations.init()使用,但不能同时!

其他说明:

  • 当您使用JUnit 4.x之后,你不需要让你的测试方法的名称由test开头,因为这些是由@Test注释您可以命名他们为你想要的任何这是可读和表达的意图的测试。
  • 设置和拆卸方法也一样,因为它们分别由@Before@After注释,您可以描述设置或拆卸的方式。
  • 最后,不要将您的测试类别命名为PluginTestCase,后缀TestCase仅用于抽象类,这些抽象类将通过后缀为Test的实际测试扩展,如MyClassTest。无论如何,Maven Surefire会寻找名为*Test的课程。
+0

请参阅我的更新,另外根据您的回答,Mockito将如何启动Spring上下文并获取bean? –

+1

噢,我正在使用Mockito 1.9rc,Mockito 1.8.5需要你实例化需要注入的字段。看看这个消息异常,这是非常明显的。Mockito努力做好错误报告以及正确使用API​​的方式。 (我相应地更新了我的答案)。 – Brice

+0

谢谢,完美无瑕。 –