2012-05-29 136 views
1

模拟使用mockito的方法确保嘲笑的方法永远不会被调用?我有主类,其中包含我想要编写单元测试的一些代码,我有一个单元测试类MainTest,其中包含主类的单元测试。嘲笑使用Mockito的方法

例如:

来源类别:

package abc; 

public class Main { 

    public int check1() { 
     int num = 10; 
     num = modify(num); 
     return num; 
    } 

    public int modify(int num) { 
     if (num % 10 == 0) return num/10; 
     return -1; 
    } 
} 

JUnit测试(使用的Mockito)

package abc; 

import junit.framework.Assert; 

import org.junit.BeforeClass; 
import org.junit.Test; 
import org.mockito.Mockito; 

public class MainTest { 

    private static Main main; 

    @BeforeClass 
    public static void setUp() { 
     main = Mockito.mock(Main.class); 
     Mockito.when(main.modify(10)).thenReturn(5); 
    } 

    @Test 
    public void testCheck1() { 
     Test1 main1 = new Main(); 
     int num = main.check1(); 
     Assert.assertEquals(5, num); 
    } 
} 

该测试失败。为什么?

回答

8

EDITED 因为您没有提供check1()的行为。 全部方法被嘲弄,所以如果没有你提供的行为,check1()返回int的返回类型的默认值,它是0.此外,check1(),因为它被嘲笑甚至没有打电话给modify()

如果您试图测试一个班级,那么您绝对不会嘲笑正在测试的班级。在极少数情况下,你可能不得不窥视一门被测试的课程。相反,你只是模拟合作者。

我猜你的例子是一个人为的(我希望)。但是,如果你正在编写和测试类,你想你想修改一些内部方法的行为,我看到了两个可能的概率:

  1. 您可能需要重构法的功能,你需要模拟出成一个合作者类。那么继续前进并嘲笑作为合作者的行为是有道理的。
  2. 您可能还可能需要修改API,以便您可以传入将要更改的内容。在你的情况下,check1()硬编码它传递给modify()的值,这就是你试图模拟modify()的原因。如果相反,该值是check1()的参数或类Main中的可设置字段,则根本不需要使用模拟。
+0

我可以嘲笑一类的一种方法,而不是整个类。就像在这种情况下修改()不是check1()? –

+0

这就是'spy()'(或'@ Spy'注释)进入的地方,而不是'mock()'。间谍将使用对象的实际实例,并且只在测试明确表达的地方覆盖行为。 –

4

问题与您的测试是,您不使用您新创建的main1对象。

如果你想改变下测试(SUT)你SYSTEN的行为,你通常会做这样的事情:

@Test 
public void testCheck1() { 
    Test1 main1 = new Main(){ 
     public int modify(int num) { 
      return 5; // hard coded return value 
     } 
    }; 
    int num = main1.check1(); 
    Assert.assertEquals(5, num); 
} 

这就造成主要的子类有一个新的实施修改法的。 这是替换SUT中难以测试的方法的重要技术。您通常会使用它来避免昂贵的远程呼叫或类似情况。

当然,可以使用间谍的Mockito这样的:

@Test 
public void testCheck1() { 
    Test1 main1 = spy(new Main()); 
    stub(main1.modify(10)).toReturn(5); 

    int num = main1.check1(); 
    Assert.assertEquals(5, num); 
} 
+0

['stub()'](http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#stub(T))被认为比使用'when()'更不可读给Mockito的作者(对此的评论在上面的Javadoc链接中)。但它不被弃用,所以我想这是可以的。另外,如果用户已经拥有Mockito,那么使用间谍似乎比声明内部类部分覆盖行为更清晰。 –

+0

我会同意使用when()而不是stub() - 它似乎主要是一种语义差异。 – VivaceVivo

+0

但我更喜欢在我的SUT上进行修改的内部类,因为它们在大多数真实世界的场景中更加灵活,并且对SUT的影响最小。简而言之:我使用mock作为我喜欢隔离的依赖对象;我使用内部类来组成SUT来使用模拟并替换一些方法。 – VivaceVivo

0

虽然我迟到了,这可能是一些有用的一个。只需添加到@VivaceVivo答案:在使用间谍时,请考虑doReturn | Answer | Throw()方法存根。有时使用(对象)来存储间谍是不可能或不切实际的。更多信息here