2013-03-26 87 views
7

我在我的应用程序中使用了spring,我想为我的所有类编写单元测试。我从我的应用程序调用几个外部Web服务,我想用Mockito来嘲笑它们,因为我只是想测试我的功能。在弹簧中使用Mockito注释

可以说我有以下情形

这是我的web界面

public interface MyWebService { 
    public String getSomeData(int id); 
} 

我使用上述服务这样

public interface MyService { 
    int doSomethingElse(String str); 
} 

public class MyServiceImpl implements MyService { 

    private MyWebService myWebService; 

    int doSomethingElse(String str) { 
     ..... 
     myWebService.getSomeData(id); 
     ... 
    } 
} 

public interface MyService1 { 
    Stirng methodToBeTested(); 
} 


public class Class1 implements MyService1{ 
    @Resource 
    private MyService myService; 

    public Stirng methodToBeTested() { 
     myService.doSomethingElse(".."); 
    } 
} 

我写了如下的UINT测试用例。我在这里监视MyService以运行单元测试。

public class class1Test { 

    @Spy 
    MyService myService; 

    @Resource 
    @InjectMocks 
    Class1 class1; 

    public void setUPTest() { 
     MockitoAnnotations.initMocks(this); 
    Mockito.doReturn(123).when(myService).doSomethingElse("someString"); 
    } 

    @Test 
    public void methodToBeTestedTest() { 
     this.setUPTest(); 
      ... 
      class1.methodToBeTested(); 
    } 

} 

当我运行测试时,我看到的是,我从Web服务中得到的值是我在提到时存在的问题。

任何人都可以帮助我吗? (和如有用的断言是否存在过渡的方法调用的)

+0

参见http://stackoverflow.com/questions/2457239/injecting-mockito-mocks-into-a-spring-bean – Vadzim 2013-10-17 10:57:00

回答

5

我用的Spring Java配置解决了这个。我在我的测试配置文件中扩展了我的默认配置文件。

@Configuration 
    public class TestConfig extends DefaultConfig { 

     @Bean 
     public MyService myService() { 
     return Mockito.spy(new MyServiceImpl()); 
     } 
    } 

现在我的测试类是这样

public class class1Test { 

    @Resource 
    MyService myService; 

    @Resource 
    Class1 class1; 

    public void setUPTest() { 
     MockitoAnnotations.initMocks(this); 
    Mockito.doReturn(123).when(myService).doSomethingElse("someString"); 
    } 

    @Test 
    public void methodToBeTestedTest() { 
     this.setUPTest(); 
      ... 
      class1.methodToBeTested(); 
    } 

} 
3

一个@Spy被用来监视呼叫服务时会发生什么,你想要什么@Mock注释:

public class class1Test { 
    @Mock MyService myService; 
    ... 

这将导致所有myService方法返回null,禁止那些用doReturn/when覆盖的方法。

顺便提一句,与其从您的测试方法中调用setUpTest(),您应该用@Before对其进行注释。

干杯,

+0

我已经在这里使用间谍,因为,MyService中还有其他方法,需要将stubbed(这只是一个示例代码,类似于我的代码) – rahul 2013-03-26 11:43:52

1

这应该适合你的需要:

@RunWith(MockitoJunitRunner.class) 
public class class1Test { 

    @Mock 
    private MyService myService; 

    private Class1 class1; 

    @Before 
    public void setUp() { 
     this.class1 = new Class1(myService); // creates this constructor. 
    } 

    @Test 
    public void methodToBeTestedTest() { 
     this.class1.methodToBeTested(); 
     Mockito.verify(this.myService).doSomethingElse(/* put expected arg here */); 
    } 
} 

又见official doc

2

你的意思是anyString()而不是你的setUp方法中的“someString”?这也可以是eq("someString")如果您使用特定字符串调用您的方法。

从我对Mockito的理解我不使用间谍,因为他们可能表明类设计问题。你为什么不@Mock整个MyService,所以;

@Mock MyService myService; 


public void setUpTest() { 
    MockitoAnnotations.initMocks(this); 
    when(myService.doSomethingElse(anyString)).thenReturn(123); 
} 
+0

@coder我有类似的类设计,直到我来测试它,当我意识到我的课是做太多的事情使得单元测试很难。考虑将Web服务工作分解为一个处理程序类。这样你就可以用模拟处理器构造你的类,并消除这个'''@ Spy''''。任何对ws的调用都可以简单地用传统的非间谍工具来嘲弄。 – OceanLife 2013-03-26 11:49:30

+0

这将解决问题,但可悲的是,我不能改变MyService或MyServiceImpl的原始实现。 – rahul 2013-03-26 11:56:08

+0

啊对,是的,你是正确的使用间谍。我没有意识到。处理第三方/遗留代码时,它们特别有用。我对Matchers的建议会产生更好的嘲讽结果吗? – OceanLife 2013-03-26 11:59:50

1

修改,

public class class1Test { 

    @Mock 
    private MyService myService; 

    private Class1 class1; 

    @Before 
    public void onceBeforeEachTest() { 
     MockitoAnnotations.initMocks(this); 
     this.class1 = new Class1(myService); 
     Mockito.when(myService).doSomethingElse(anyString()).thenReturn(123); 
    } 

    @Test 
    public void methodToBeTestedTest() { 
      class1.methodToBeTested(); 
    } 
} 
+0

我没有一个构造函数,它将一个对象作为参数。 – rahul 2013-03-26 11:53:38

3

要故作取代你在Bean的一些测试使用Springockito或更好Springockito-annotations

像这样的东西应该工作:

@ContextConfiguration(loader = SpringockitoContextLoader.class, 
    locations = "classpath:/context.xml") 
public class SpringockitoAnnotationsMocksIntegrationTest extends AbstractJUnit4SpringContextTests { 

    @WrapWithSpy 
    private MyService innerBean; 

    @Resource 
    Class1 class1; 

    public void setUPTest() {   
     Mockito.doReturn(123).when(myService).doSomethingElse("someString"); 
    } 

    @Test 
    public void methodToBeTestedTest() { 
    this.setUPTest(); 
     ... 
     class1.methodToBeTested(); 
    } 

}

+0

我已经看过上面的链接。如何使用springockito将“myService”间谍注入“class1”。在Class1中,“我的服务”是私人的,没有设置者。 – rahul 2013-03-26 13:17:13

+0

@coder,已更新。如果在真实环境中,myService被注入到Class1中 - 它也会被注入WrapWithSpy。 – 2013-03-26 13:31:20

+0

我使用spring java配置进行bean的初始化,springockito dosent支持它。 – rahul 2013-03-28 07:25:04