web-dev-qa-db-ja.com

ENUMクラスのメソッドをモックする方法は?

私は以下のENUmクラスのJUNITテストケースの作成に取り組んでいます。以下のクラスは、コードを実行している現在のマシンのホスト名のみを提供します。 JUNITテストを書いているときに、以下のクラスをモックして、いつでもgetHostName()メソッドを変更して、getDatacenter()を呼び出すたびに返すことができるようにするにはどうすればよいですか。私がそれをあざけることによって渡すどんなホスト名でも。パラメータ化されたものにしたくありません。

ホスト名をモックしながら変更しながら、特定のケースをテストしたいだけです。

public enum DatacenterEnum {
    DEV, DC1, DC2, DC3;


    public static String forCode(int code) {
    return (code >= 0 && code < values().length) ? values()[code].name() : null;
    }
    private static final String getHostName() {
        try {
            return InetAddress.getLocalHost().getCanonicalHostName().toLowerCase();
        } catch (UnknownHostException e) {
            s_logger.logError("error = ", e);
        }

        return null;
    }

    public static String getDatacenter() {
        return getHostName();
    }
}
9
user2467545

データセンターインターフェイスを作成し、列挙型にインターフェイスを実装させることができます。これにより、モックがより簡単になります。

何よりも、最初から構成情報を列挙型に配置することはしません。他のデータセンターを追加する必要がある場合(またはデータセンターの構成を変更する場合)は、コードを再コンパイルする必要があります。たとえば、JavaプロパティファイルまたはXMLファイル)などの通常のクラス読み取りに構成を配置することを検討してください(この関数は、フレームワークにすでに実装されている可能性があります)。

これが不可能な場合は、「darkes reflaction」マジックを使用して、列挙型のフィールドを必要な値に変更できます。

1
Tobias Kremer

可能ですが、これは非推奨です。コードをリファクタリングすることをお勧めします。

Mockito/PowerMockの実例

@RunWith(PowerMockRunner.class)
@PrepareForTest(DatacenterEnum.class)
public class DatacenterEnumTest {

    @Mock
    InetAddress inetAddress;

    @Test
    public void shouldReturnDatacenter() throws UnknownHostException {
        //given
        mockStatic(InetAddress.class);
        given(inetAddress.getCanonicalHostName()).willReturn("foo");
        given(InetAddress.getLocalHost()).willReturn(inetAddress);

        //when
        String datacenter = DatacenterEnum.getDatacenter();

        //then
        assertThat(datacenter).isEqualTo("foo");
    }
}

依存関係

  • org.powermock:powermock-module-junit4:1.5.2
  • org.powermock:powermock-api-mockito:1.5.2
  • org.assertj:assertj-core:1.5.0
  • junit:junit:4.11
1
MariuszS

JMockitを使えば簡単です。

_@Test
public void mockInetAddress(@Cascading final InetAddress inetAddress)
{
    new NonStrictExpectations() {{
        inetAddress.getCanonicalHostName(); result = "foo";
    }};

    String datacenter = DatacenterEnum.getDatacenter();

    assertEquals("foo", datacenter);
}
_

もちろん、列挙型のgetHostName()メソッドをモックすることもできますが、privateメソッドをモックすることは避けるのが最善です。

1
Rogério

私は古い学校かもしれませんが、クラスローダーのハックを使用するのではなく、テスト対象のコードを実際にリファクタリングしたいと思います。何かのようなもの:

public enum DatacenterEnum {
    DEV, DC1, DC2, DC3;


    static String hostName = InetAddress.getLocalHost().getCanonicalHostName().toLowerCase();

    public static String getHostName() {
        return hostName;
    }
}

テストを実行する前に、テストコードで次のことを行います。

DataCenterEnum.hostName = "foo";
0
meriton

これは、Mockito/Powermockでそれを行うことができる方法です。 Mockitoは静的な方法をモックできないため、Powermockが必要です。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest({DatacenterEnum.class})
public class DatacenterEnumTest {

    @Test
    public void testGetDatacenter() {
        mockStatic(DatacenterEnum.class);
        when(DatacenterEnum.getDatacenter()).thenReturn("YourHostname");

        String datacenter = DatacenterEnum.getDatacenter();

        assertEquals("YourHostname", datacenter);
    }
}

Mavenの依存関係

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito</artifactId>
        <version>1.5.2</version>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>1.5.2</version>
    </dependency>
</dependencies>
0
Philipp Hofmann