2013-05-01 119 views
0

是否可以在构造函数中使用模拟?在构造函数中使用模拟

Class A{ 

    public B b = new B(); 

    public A(String input){ 

     //I need to stub this method 
     b.someMethod(input); 
    } 

    // Class implementations 
} 

单元测试:

Class ATest{ 

    @Mock 
    B b; 
    @InjectMock 
    A a; 

    //option1: 
    @Before 
    setup(){ 
     MockitoAnnotations.initMocks(this); //Fails - since A isnt instantiated 
     a = new A(); 
    } 

    //option2: 
    @Before 
    setup(){ 
     a = new A(); 
     MockitoAnnotations.initMocks(this); // Fails in new A() due to method i want to stub as mocks werent initialized yet ! 
    } 
} 

我该如何处理这个?提前致谢。

+2

你真的应该避免在构造函数中做逻辑。 – vertti 2013-05-01 04:53:54

+0

如果您省略'a = new A();',选项1会失败吗?我希望'@ InjectMocks'注释可以在调用'initMocks'的时候为你实例化'A'。对于备用选项,您可能会从https://code.google.com/p/mockito/wiki/MockingObjectCreation获得一些乐趣 – 2013-05-01 05:48:25

+0

是的,它没有抱怨它必须实例化 – broun 2013-05-02 04:59:02

回答

7

这种设计很难嘲笑,揭示可能存在设计缺陷或在测试下你的班上至少弱点。它可能需要某种注入框架(即Spring),所以你没有明确地调用B构造函数。然后你的第二次测试尝试将在现场

如果春天是太过沉重,有较轻的注射框架。或者最后,你可以传递B作为A的构造函数参数。然后,你必须使用Mockito.mock(B.class)在将它传递给A构造函数之前进行B模拟(然后您将放弃使用Mockito注释)。

+0

首先感谢回复。是的,就像你说春季注射会起作用,但这个类是图书馆的一部分,并且不应该强制Spring依赖。你提到的第二个选项可以工作,但我希望如果有一个干净的解决方案的问题。 – broun 2013-05-01 05:13:26

0

我不明白你想从中做什么,但你的第二种方法是正确的。只有你需要像B类一样实例化B类。所以,基本上这是所有你需要做的:

//option2: 
@Before 
setup(){ 

a = new A(); 
b = new B(); 
MockitoAnnotations.initMocks(this); // Fails in new A() due to method i want to stub as  mocks werent initialized yet ! 

} 
} 
+0

我可能是错的,但我认为你错过了点。 Setafire想嘲笑B,但你正在实例化真实的。 – 2013-05-01 04:41:00