【问题标题】:For what reason should I mock?我应该嘲笑什么?
【发布时间】:2013-02-16 02:39:01
【问题描述】:

我也是 Mockito 和 PowerMockito 的新手。我发现我无法使用纯 Mockito 测试静态方法,所以我需要使用 PowerMockito(对吗?)。

我有一个非常简单的类,叫做 Validate 用这个非常简单的方法

public class Validate {
        public final static void stateNotNull(
            final Object object,
            final String message) {
    if (message == null) {
        throw new IllegalArgumentException("Exception message is a null object!");
    }
    if (object == null) {
        throw new IllegalStateException(message);
    }
}

所以我需要验证一下:

1) 当我在 null 消息参数上调用该静态方法时,会调用 IllegalArgumentException
2)当我在空对象参数上调用该静态方法时,会调用 IllegalStateException

根据我目前的情况,我编写了这个测试:

import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.isNull;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.testng.annotations.Test;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Validate.class)
public class ValidateTestCase {

    @Test(expectedExceptions = { IllegalStateException.class })
    public void stateNotNullTest() throws Exception {
        PowerMockito.mockStatic(Validate.class);
        Validate mock = PowerMockito.mock(Validate.class);
        PowerMockito.doThrow(new IllegalStateException())
            .when(mock)
            .stateNotNull(isNull(), anyString());
        Validate.stateNotNull(null, null);
    }
}

所以这表示我模拟了 Validate 类,并且我正在检查当使用 null 参数作为对象和任何字符串作为消息对该方法调用模拟时,是否会引发 IllegalStateException。

现在,我真的不明白。为什么我不能直接调用那个方法,放弃整个巫术魔法来模拟那个静态类?在我看来,除非我调用 Validate.stateNotNull,否则测试无论如何都会通过......我应该模拟它的原因是什么?

【问题讨论】:

    标签: java unit-testing testing junit mockito


    【解决方案1】:

    您不应该模拟您正在测试的类和方法。您应该只模拟执行测试所需的方法。

    例如,如果您需要来自 Web 服务的一些对象来执行测试,您可以模拟 Web 服务调用,因此您不需要实际调用 Web 服务。

    【讨论】:

      【解决方案2】:

      首先,确定您的目标是什么以及您要测试什么。您的测试不是在测试您的 Validate 类方法,而是在创建一个行为类似于该方法的模拟,如 Fortega points out。确定您正在测试什么(被测对象)以及执行测试所需的内容(协作者),然后查看协作者并确定它们是否易于创建或是否需要嘲笑他们。

      对于像此类不依赖任何东西的东西,我建议完全不使用模拟。这里没有什么需要 mock 的,测试可以这样写:

      import static org.junit.Assert.*;
      
      public class ValidateTestCase {
      
          @Test
          public void testHappyPath() throws Exception {
              Validate.stateNotNull("", "");
          }
      
          @Test
          public void testNullMessage() throws Exception {
              try {
                  Validate.stateNotNull(null, null);
                  fail();
              }
              catch (IllegalStateException e) {
                  String expected = "Exception message is a null object!"
                  assertEquals(expected, e.getMessage());
              }
          }
      
          @Test(expected=IllegalStateException.class)
          public void testNullObject() throws Exception {
              Validate.stateNotNull(null, "test");
          }
      }
      

      这会告诉您代码是否按照您的意愿行事。

      不要模拟,除非由于它是外部资源(如文件系统或数据库)或某些复杂的子系统,您希望避免将某些依赖项引入测试。模拟框架可能非常有用,但它们增加了复杂性,它们可以过度指定它们正在测试的事物的行为,使测试变得脆弱,并且它们可能使测试难以阅读。如果可以,请不要使用它们。

      【讨论】:

        猜你喜欢
        • 2010-09-07
        • 1970-01-01
        • 2011-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-26
        • 2014-05-27
        相关资源
        最近更新 更多