Java 初始化模拟对象-MockIto

Java 初始化模拟对象-MockIto,第1张

Java 初始化模拟对象-MockIto

对于模拟初始化,使用

Runner
或是
MockitoAnnotations.initMocks
严格等效的解决方案。从MockitoJUnitRunner的javadoc中:

JUnit 4.5 runner initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary. Mocks are initialized before each test method.

MockitoAnnotations.initMocks
当你已经
SpringJUnit4ClassRunner
测试用例上配置了特定的运行器时,可以使用第一个解决方案(带有)。

第二个解决方案(带有

MockitoJUnitRunner
)更经典,也是我的最爱。代码更简单。使用转轮提供了很大的优势框架使用的自动验证。

两种解决方案都可以在测试方法之间共享模拟(和间谍)。与结合使用@InjectMocks,它们可以非常快速地编写单元测试。样板代码减少了,测试更易于阅读。例如:

@RunWith(MockitoJUnitRunner.class)public class ArticleManagerTest {    @Mock private ArticleCalculator calculator;    @Mock(name = "database") private ArticleDatabase dbMock;    @Spy private UserProvider userProvider = new ConsumerUserProvider();    @InjectMocks private ArticleManager manager;    @Test public void shouldDoSomething() {        manager.initiateArticle();        verify(database).addListener(any(ArticleListener.class));    }    @Test public void shouldDoSomethingElse() {        manager.finishArticle();        verify(database).removeListener(any(ArticleListener.class));    }}

优点:代码很少

缺点:黑魔法。IMO这主要是由于@InjectMocks注释。有了这个注释, “你可以放松代码的痛苦”(请参阅@Brice的精彩评论)

第三种解决方案是在每个测试方法上创建模拟。正如@mlk在其答案中所解释的,它允许进行“ 自包含测试 ”。

public class ArticleManagerTest {    @Test public void shouldDoSomething() {        // given        ArticleCalculator calculator = mock(ArticleCalculator.class);        ArticleDatabase database = mock(ArticleDatabase.class);        UserProvider userProvider = spy(new ConsumerUserProvider());        ArticleManager manager = new ArticleManager(calculator,         userProvider,         database);        // when         manager.initiateArticle();        // then         verify(database).addListener(any(ArticleListener.class));    }    @Test public void shouldDoSomethingElse() {        // given        ArticleCalculator calculator = mock(ArticleCalculator.class);        ArticleDatabase database = mock(ArticleDatabase.class);        UserProvider userProvider = spy(new ConsumerUserProvider());        ArticleManager manager = new ArticleManager(calculator,         userProvider,         database);        // when         manager.finishArticle();        // then        verify(database).removeListener(any(ArticleListener.class));    }}

优点:你可以清楚地演示api的工作原理(BDD …)

缺点:还有更多样板代码。(模拟创作)

我的建议是妥协。将

@Mock
注释与一起使用
@RunWith(MockitoJUnitRunner.class)
,但不要使用
@InjectMocks

@RunWith(MockitoJUnitRunner.class)public class ArticleManagerTest {    @Mock private ArticleCalculator calculator;    @Mock private ArticleDatabase database;    @Spy private UserProvider userProvider = new ConsumerUserProvider();    @Test public void shouldDoSomething() {        // given        ArticleManager manager = new ArticleManager(calculator,         userProvider,         database);        // when         manager.initiateArticle();        // then         verify(database).addListener(any(ArticleListener.class));    }    @Test public void shouldDoSomethingElse() {        // given        ArticleManager manager = new ArticleManager(calculator,         userProvider,         database);        // when         manager.finishArticle();        // then         verify(database).removeListener(any(ArticleListener.class));    }}

优点:你可以清楚地演示api的工作原理(如何ArticleManager实例化my )。没有样板代码。

缺点:测试不是独立的,代码痛苦更少



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5432148.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-11
下一篇2022-12-11

发表评论

登录后才能评论

评论列表(0条)

    保存