有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

我为什么要嘲笑java?

我对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) 当我在null对象参数上调用该静态方法时,将调用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参数作为对象,以任何字符串作为消息对该方法调用mock时,是否抛出了IllegalStateException

现在,我真的不明白。为什么我不能直接调用那个方法,放弃了所有的巫毒魔法来模拟那个静态类?在我看来,除非我打电话确认。stateNotNull表示测试仍然通过。。。我为什么要嘲笑它


共 (2) 个答案

  1. # 1 楼答案

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

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

  2. # 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");
        }
    }
    

    这会告诉你代码是否符合你的要求

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