在没有 PowerMock 的情况下监视 class
Spy a class without PowerMock
我不想再使用 powermock 了。因为 junit5 开始模拟静态 classes。所以我试图摆脱 powermock 方法。
当我使用 PowerMock 时,我可以很容易地发现一个 class 有一个私有构造函数,然后我调用静态方法。
这是我的代码的一部分(当我使用 PowerMock 时)
@RunWith(PowerMockRunner.class)
@PrepareForTest(MessageValidationUtils.class)
public class MessageValidationServiceTest {
@Mock
private CheckpointCustomerService checkpointCustomerService;
@Mock
private ProductClientService productClientService;
@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
PowerMockito.spy(MessageValidationUtils.class);
}
在我制作 MessageValidationUtils.class 的间谍对象后,我正在测试这个:
when(MessageValidationUtils.validateTelegramKeyMap(messageProcessDto.getMessageMessageType(),
messageProcessDto.getMessageKeyValueMap())).thenAnswer((Answer<Boolean>) invocation -> true);
经过一番研究,我找不到任何与间谍相关的东西 class 具有私有构造函数和静态方法。
在 Mockito 中的 mockStatic
定义期间,您可以指定设置以默认执行实际执行 Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS)
。这样,您的静态模拟将像 Spy
一样工作。
让我们创建简单的 Utils
class 进行测试。
public class Utils {
public static String method1() {
return "Original mehtod1() value";
}
public static String method2() {
return "Original mehtod2() value";
}
public static String method3() {
return method2();
}
}
模拟 method2
并执行 method1
和 method3
的实际执行
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class SpyStaticTest {
@Test
public void spy_static_test() {
try (MockedStatic<Utils> utilities = Mockito.mockStatic(Utils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))) {
utilities.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
}
}
您的 class 示例:
@Test
public void test() {
try (MockedStatic<MessageValidationUtils> utilities = Mockito.mockStatic(MessageValidationUtils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))) {
utilities.when(() -> MessageValidationUtils.validateTelegramKeyMap(messageProcessDto.getMessageMessageType(),
messageProcessDto.getMessageKeyValueMap())).thenAnswer((Answer<Boolean>) invocation -> true);
//perform testing of your service which uses MessageValidationUtils
}
}
更新:
在 @BeforeEach
中使用 mockStatic
的示例
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class SpyStaticTest {
MockedStatic<Utils> utilities;
@BeforeEach
public void setUp() {
utilities = Mockito.mockStatic(Utils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
}
@Test
public void spy_static_test1() {
utilities.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
@Test
public void spy_static_test2() {
utilities.when(Utils::method1).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "static mock");
Assertions.assertEquals(Utils.method2(), "Original mehtod2() value");
Assertions.assertEquals(Utils.method3(), "Original mehtod2() value");
}
@AfterEach
public void afterTest() {
utilities.close();
}
}
更新:
Mockito 不提供创建静态 Spy
的方法,但您可以在那里定义自己的 utils 和 implemet spy 静态定义。
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class MockitoUtils {
public static <T> MockedStatic<T> spyStatic(Class<T> classToMock) {
return Mockito.mockStatic(classToMock, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
}
}
这样你的测试看起来会更清晰:
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static com.test.MockitoUtils.spyStatic;
public class SpyStaticTest {
MockedStatic<Utils> utilsSpy;
@BeforeEach
public void setUp() {
utilsSpy = spyStatic(Utils.class);
}
@Test
public void spy_static_test1() {
utilsSpy.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
@Test
public void spy_static_test2() {
utilsSpy.when(Utils::method1).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "static mock");
Assertions.assertEquals(Utils.method2(), "Original mehtod2() value");
Assertions.assertEquals(Utils.method3(), "Original mehtod2() value");
}
@AfterEach
public void afterTest() {
utilsSpy.close();
}
}
我不想再使用 powermock 了。因为 junit5 开始模拟静态 classes。所以我试图摆脱 powermock 方法。
当我使用 PowerMock 时,我可以很容易地发现一个 class 有一个私有构造函数,然后我调用静态方法。
这是我的代码的一部分(当我使用 PowerMock 时)
@RunWith(PowerMockRunner.class)
@PrepareForTest(MessageValidationUtils.class)
public class MessageValidationServiceTest {
@Mock
private CheckpointCustomerService checkpointCustomerService;
@Mock
private ProductClientService productClientService;
@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
PowerMockito.spy(MessageValidationUtils.class);
}
在我制作 MessageValidationUtils.class 的间谍对象后,我正在测试这个:
when(MessageValidationUtils.validateTelegramKeyMap(messageProcessDto.getMessageMessageType(),
messageProcessDto.getMessageKeyValueMap())).thenAnswer((Answer<Boolean>) invocation -> true);
经过一番研究,我找不到任何与间谍相关的东西 class 具有私有构造函数和静态方法。
在 Mockito 中的 mockStatic
定义期间,您可以指定设置以默认执行实际执行 Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS)
。这样,您的静态模拟将像 Spy
一样工作。
让我们创建简单的 Utils
class 进行测试。
public class Utils {
public static String method1() {
return "Original mehtod1() value";
}
public static String method2() {
return "Original mehtod2() value";
}
public static String method3() {
return method2();
}
}
模拟 method2
并执行 method1
和 method3
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class SpyStaticTest {
@Test
public void spy_static_test() {
try (MockedStatic<Utils> utilities = Mockito.mockStatic(Utils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))) {
utilities.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
}
}
您的 class 示例:
@Test
public void test() {
try (MockedStatic<MessageValidationUtils> utilities = Mockito.mockStatic(MessageValidationUtils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))) {
utilities.when(() -> MessageValidationUtils.validateTelegramKeyMap(messageProcessDto.getMessageMessageType(),
messageProcessDto.getMessageKeyValueMap())).thenAnswer((Answer<Boolean>) invocation -> true);
//perform testing of your service which uses MessageValidationUtils
}
}
更新:
在 @BeforeEach
mockStatic
的示例
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class SpyStaticTest {
MockedStatic<Utils> utilities;
@BeforeEach
public void setUp() {
utilities = Mockito.mockStatic(Utils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
}
@Test
public void spy_static_test1() {
utilities.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
@Test
public void spy_static_test2() {
utilities.when(Utils::method1).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "static mock");
Assertions.assertEquals(Utils.method2(), "Original mehtod2() value");
Assertions.assertEquals(Utils.method3(), "Original mehtod2() value");
}
@AfterEach
public void afterTest() {
utilities.close();
}
}
更新:
Mockito 不提供创建静态 Spy
的方法,但您可以在那里定义自己的 utils 和 implemet spy 静态定义。
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class MockitoUtils {
public static <T> MockedStatic<T> spyStatic(Class<T> classToMock) {
return Mockito.mockStatic(classToMock, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
}
}
这样你的测试看起来会更清晰:
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static com.test.MockitoUtils.spyStatic;
public class SpyStaticTest {
MockedStatic<Utils> utilsSpy;
@BeforeEach
public void setUp() {
utilsSpy = spyStatic(Utils.class);
}
@Test
public void spy_static_test1() {
utilsSpy.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
@Test
public void spy_static_test2() {
utilsSpy.when(Utils::method1).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "static mock");
Assertions.assertEquals(Utils.method2(), "Original mehtod2() value");
Assertions.assertEquals(Utils.method3(), "Original mehtod2() value");
}
@AfterEach
public void afterTest() {
utilsSpy.close();
}
}