有很多方法可以使用MockIto初始化模拟对象.

1.

 public class SampleBaseTestCase {

   @Before public void initMocks() {
       MockitoAnnotations.initMocks(this);
   }
@RunWith(MockitoJUnitRunner.class)
mock(XXX.class);

如果还有比这些更好的方法,请建议我...

推荐答案

使用流道或MockitoAnnotations.initMocks是严格等价的解决方案.从MockitoJUnitRunner个国家的javadoc:

JUnit 4.5 runner初始化用Mock注释的Mock,以便显式使用MockitoAnnotations.initMocks(对象)不是必需的.在每个测试方法之前,都会初始化模拟.


当您已经在测试用例上配置了特定的运行程序(例如SpringJUnit4ClassRunner)时,可以使用第一个解决方案(使用MockitoAnnotations.initMocks).

第二种解决方案(MockitoJUnitRunner)更classic ,也是我最喜欢的.代码更简单.使用流道提供了100的巨大优势(由this answer中的@David Wallace描述).

这两种解决方案都允许在测试方法之间共享模拟(和间谍).再加上@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这主要是由于@InjectMock注释造成的.使用此注释"you loose the pain of code"(请参阅@Brice的精彩注释)


第三个解决方案是在每个测试方法上创建您的模拟. 正如@mlk在其答复中所解释,它允许具有"self contained test".

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…)

缺点:有更多的样板代码.(模仿创作)


My建议是一种妥协.使用@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是如何工作的(my ArticleManager是如何实例化的).没有样板代码.

缺点:测试不是自包含的,代码痛苦较少

Java相关问答推荐

表格栏上的事件过滤器在PFA中不起作用

Maven Google Sheets版本问题

int Array Stream System. out. print方法在打印Java8时在末尾添加% sign

OpenJDK、4K显示和文本质量

如何在Javascript中设置文本区域圆角的样式

在AnyLogic中增加变量计数

如何在带有Micronaut的YAML中使用包含特殊字符的字符串作为键

Spring Boot 3.2.2中的@Inject和@Resource Remove

在Java中,如何按一个属性升序,然后按另一个属性降序对对象列表进行排序?

AbstractList保证溢出到其他方法

将stringBuilder + forloop转换为stream + map

如果第一位数字和最后一位数字相差超过一位,您将如何获得随机数?

对角线填充二维数组

在应用程序运行时更改LookAndFeel

在Oracle中调用输出参数在索引处缺少IN或OUT参数的函数

模拟JUnit未检测到返回字符串的方法的任何声纳覆盖

Kotlin-仅替换字符串中最后一个给定的字符串

如何利用OpenTelemeter将初始值(零)输出到普罗米修斯

如何在Spring Security中设置一个任何人都可以打开的主页?

rest api服务 spring 启动中出现IllegalFormatConversionException