mockito 如何在Springboot中使用WebMvcTest模拟静态函数

qoefvg9y  于 2022-11-08  发布在  Spring
关注(0)|答案(1)|浏览(77)

在@WebMvcTest注解中是否有任何功能可以用来测试类别的静态函式?

6tr1vspr

6tr1vspr1#

因为我相信我找到了它(它在baeldung-tutorial链接中是缺少的),这里有一个例子(我目前不使用@WebMvcTest,我正在测试一个配置对象):

(请参阅下面的说明)

(imports omitted in favor of brevity)

@Slf4j
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ServerObjectConfiguration.class)
class ServerObjectConfigurationTest {

    // 192.168.178.82
    private static final byte[] EXAMPLE_IP_V4 = {-64, -88, -78, 82};
    // 2001:0db8:85a3:0000:0000:8a2e:0370:7334
    private static final byte[] EXAMPLE_IP_V6 = {32, 1, 13, -72, -123, -93, 0, 0, 0, 0, -118, 46, 3, 112, 115, 52};
    private static final byte[] EXAMPLE_MAC_ADDRESS = {-68, -48, 116, 9, -47, 11};
    private static final MockedStatic<NetworkInterface> mockedNetworkInterface = Mockito.mockStatic(NetworkInterface.class);
    private static final MockedStatic<InetAddress> mockedInetAddress = Mockito.mockStatic(InetAddress.class);

    @Autowired
    private ServerObjectConfiguration serverObjectConfiguration;

    @Autowired
    private Server server;

    @SneakyThrows
    @BeforeAll
    static void setUp() {
        // This is SPARTAAA... or rather: crazy, because everything java.net seems to smell of bad design decisions
        InetAddress ipV4InetAddress = mock(InetAddress.class);
        when(ipV4InetAddress.getAddress())
                .thenReturn(EXAMPLE_IP_V4);
        when(ipV4InetAddress.isSiteLocalAddress())
                .thenReturn(true);

        InetAddress ipV6InetAddress = mock(InetAddress.class);
        when(ipV6InetAddress.getAddress())
                .thenReturn(EXAMPLE_IP_V6);
        when(ipV6InetAddress.isSiteLocalAddress())
                .thenReturn(true);

        InterfaceAddress ipV4InterfaceAddress = mock(InterfaceAddress.class);
        when(ipV4InterfaceAddress.getAddress())
                .thenReturn(ipV4InetAddress);

        InterfaceAddress ipV6InterfaceAddress = mock(InterfaceAddress.class);
        when(ipV6InterfaceAddress.getAddress())
                .thenReturn(ipV6InetAddress);

        NetworkInterface networkInterface = mock(NetworkInterface.class);
        when(networkInterface.getInterfaceAddresses())
                .thenReturn(List.of(ipV4InterfaceAddress, ipV6InterfaceAddress));
        when(networkInterface.getHardwareAddress())
                .thenReturn(EXAMPLE_MAC_ADDRESS);

        mockedInetAddress.when(() -> InetAddress.getByAddress(EXAMPLE_IP_V4))
                .thenReturn(ipV4InetAddress);
        mockedInetAddress.when(() -> InetAddress.getByAddress(EXAMPLE_IP_V6))
                .thenReturn(ipV6InetAddress);

        mockedNetworkInterface.when(() -> NetworkInterface.getByInetAddress(ipV4InetAddress))
                .thenReturn(networkInterface);
        mockedNetworkInterface.when(() -> NetworkInterface.getByInetAddress(ipV6InetAddress))
                .thenReturn(networkInterface);
        mockedNetworkInterface.when(NetworkInterface::networkInterfaces)
                .thenReturn(Stream.of(networkInterface));
    }

    @AfterAll
    static void tearDown() {
        mockedInetAddress.close();
        mockedNetworkInterface.close();
    }

    @SneakyThrows
    @Test
    void test_serverObjectIsConfiguredAsExpected() {
        // the bean uses NetworkInterface to get the IP-addresses and MAC-address 
        assertThat(server.getMacAddresses()).containsOnly(EXAMPLE_MAC_ADDRESS);
        assertThat(server.getIpAddresses()).containsExactlyInAnyOrder(EXAMPLE_IP_V4, EXAMPLE_IP_V6);
    }
}

要模拟一个静态方法,让Spring Boot在Bean初始化/上下文创建过程中使用它,您必须在一个@BeforeAll(JUnit 5)注解方法中进行模拟,这个方法是静态的。原因是,您希望在测试中尽可能早地模拟静态方法。
我尝试使用线程本地的Mockito#mockStatic调用,但是由于我的bean在测试开始之前就已经初始化了,所以我尝试模拟相关的静态方法已经太晚了。
这种方法确实有效,并且包含IP地址和MAC地址的Server-bean接收到了我所期望的值。

相关问题