文書の過去の版を表示しています。
Integration with TestNG
PowermockをTestNGと一緒に使う為に必要な設定をメモとして残しておく。
基本的に、testプロジェクトはMavenプロジェクトとして作成することを前提している。
Mavenプロジェクトのproperties設定を以下に示す。
| key | value | comment |
|---|---|---|
| project.build.sourceEncoding | UTF-8 | |
| java.version | 1.8 | |
| powermock.version | 2.0.9 | |
| log4j.version | 2.17.1 |
Mavenプロジェクトのplugin設定を以下に示す。
<plugin> <groupId>ora.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin>
TestNGと一緒に使う場合は、下記モジュールの導入が必要だ。
必要モジュールを下記に示す。
| groupId | artifactId | version | scope |
|---|---|---|---|
| org.powermock | powermock-module-testng | ${powermock.version} | test |
| org.powermock | powermock-api-mockito2 | ${powermock.version} | test |
その他、必要モジュールを導入するが、基本的に入れるモジュールを以下に示す。
| groupId | artifactId | version | scope |
|---|---|---|---|
| org.dbunit | dbunit | 2.7.2 | |
| org.apache.commons | commons-lang3 | 3.12 | |
| org.apache.poi | poi | 5.1.0 | |
| org.apache.poi | poi-ooxml | 5.1.0 | |
| commons-io | commons-io | 2.11.0 | |
| commons-beanutils | commons-beanutils | 1.9.3 | |
| com.google.inject | guice | 5.0.1 | |
| org.apache.logging.log4j | log4j-1.2-api | ${log4j.version} | test |
| org.apache.logging.log4j | log4j-api | ${log4j.version} | test |
| org.apache.logging.log4j | log4j-core | ${log4j.version} | test |
Common Parent Test Class
Testクラスが共通で継承する親クラスについて、サンプルとして残しておく。
@Listeners({CustomTestMethodListener.class}) @PowerMockIgnore({"javax.management.*", "javax.security.auth.x500.*", "javax.net.ssl.*", "oracle.jdbc.*", "javax.sql.*", "com.microsoft.sqlserver.*"}) public abstract class AbstractCustomTestCase extends PowerMockTestCase { /** DBUnitのテスター */ protected IDatabaseTester databaseTester; //overwrite createWorkbook for Xlsx data set //DBUnitでXlsxをITableとして使えるよう、override protected final XlsDataSetWriter xlsxWriter = new XlsDataSetWriter() { /* (non-Javadoc) * @see org.dbunit.dataset.excel.XlsDataSetWriter#createWorkbook() */ @Override protected Workbook createWorkbook() { return new XSSFWorkbook(); } }; //***** public method ***** //***** protected method ***** @BeforeClass protected void setUp() throws Exception { setUpLog4j(); setUpDbunitTester(); prepareSpecific(); } @AfterClass protected void tearDown() throws Exception { databaseTester.setTearDownOperation(DatabaseOperation.NONE); databaseTester.onTearDown(); tearDownHook(); } protected abstract void prepareSpecific() throws Exception; protected void tearDownHook() throws Exception { //NOP } //***** private method ***** // Creates a new JdbcDatabaseTester private void setUpDbunitTester() throws Exception { DataSource _ds = DataSourceLocator.getDataSource(DBConstants.EPADS); databaseTester = new DataSourceDatabaseTester(_ds); // ---------------------------------- // Database config // ---------------------------------- DatabaseConfig _config = databaseTester.getConnection().getConfig(); _config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new OracleDataTypeFactory()); } //Enable Log4j 1.x bridge private void setUpLog4j() { System.setProperty("log4j1.compatibility", "true"); } }
@Listeners
Test実行中のあるフェーズで共通の処理を追加したい場合の為に、TestNGではListener1)というInterfaceを提供している。
通常テストを行う際、メソッド1個のみ実行することはない。
今なんのメソッドが実行されたかをコンソールで確認し易いために、IInvokeMethodListenerを実装しておくと便利だ。
サンプルのParent Classでは、CustomTestMethodListenerを指定しているが、コードを以下に示す。
public class CustomTestMethodListener implements IInvokedMethodListener { //***** injection field ***** //***** constructor ***** //***** public method ***** /** * @see org.testng.IInvokedMethodListener#beforeInvocation(org.testng.IInvokedMethod, org.testng.ITestResult) */ public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { if (method.isTestMethod()) { System.out.println("on test method " + method.getTestMethod().getMethodName() + " start"); //parameters System.out.println("parameters:" + ToStringBuilder.reflectionToString(testResult.getParameters(), ToStringStyle.SIMPLE_STYLE)); } } /** * @see org.testng.IInvokedMethodListener#afterInvocation(org.testng.IInvokedMethod, org.testng.ITestResult) */ public void afterInvocation(IInvokedMethod method, ITestResult testResult) { //NOP } }
@MockPolicy
Powermockをlog4j又はslf4jと一緒に使う場合、次のエラーが発生することがある。
log4j:ERROR A "org.apache.log4j.xml.DOMConfigurator" object is not assignable to a "org.apache.log4j.spi.Configurator" variable. log4j:ERROR The class "org.apache.log4j.spi.Configurator" was loaded by log4j:ERROR [org.powermock.core.classloader.MockClassLoader@14a55f2] whereas object of type log4j:ERROR "org.apache.log4j.xml.DOMConfigurator" was loaded by [sun.misc.Launcher$AppClassLoader@92e78c]. log4j:ERROR Could not instantiate configurator [org.apache.log4j.xml.DOMConfigurator].
解決策はいくつか2)あるが、簡単なのは、MockPolicy annotationを利用してlog実装体を指定する方法だ。
Log4jのみ利用する場合は、@MockPolicy(Log4jMockPolicy.class)
Slf4jとLog4jを併用する場合は、@MockPolicy(Slf4jMockPolicy.class)を指定する。
@PowerMockIgnore
TestNGとPowerMockを同時に使うと、TestNGのClassLoaderによりloadingされたクラスが、PowerMockerのClassLoaderにloadingされエラーになることがある。
それを回避するために、用意されているのが@PowerMockIgnore annotationになる。
サンプルのParentクラスで指定した設定の意味を次に示す。
| package or class | 目的 |
|---|---|
| javax.management.* | DBUnitと統合 |
| javax.net.ssl.* | DBUnitと統合 |
| javax.security.auth.x500.* | DBUnitと統合 |
| oracle.jdbc.* | Oracle接続 |
| javax.sql.* | SQL Server接続 |
| com.microsoft.sqlserver.* | SQL Server接続 |