IoCコンテナを使えば,テスト用にドライバ/スタブを容易にDIできる.
当然のことなのだが,意外にこの利点をあえて使わない(?)テストケースを書いてくることがままある.これを使えば当然テストコードはかなり可読性が高くなるので,使わない手はないはずだが.
以下はモックのDIの参考例.
以下の例では,DataDumpServiceのインタフェースを介してConsoleDataDumpService並びにDataNodeNodeIFインタフェースを介して テスト用データを持つDataNodeをユニットテスト中にDIする.
DataDumpServiceインタフェース
package org.tanuneko;
public interface DataDumpService {
public void dump( Object obj );
}
ConsoleDumpServiceクラス
package org.tanuneko;
import org.springframework.stereotype.Service;
@Service
public class ConsoleDataDumpService implements DataDumpService {
public void dump( Object obj ) {
System.out.println( obj );
}
}
NodeIFインタフェース
package org.tanuneko;
public interface NodeIF<X> {
public X getData();
}
DataNodeクラス
package org.tanuneko;
public class DataNode<X> implements NodeIF {
private X data;
public DataNode( X data ) {
this.data = data;
}
public X getData() {
return data;
}
}
AppConfig(非テスト用)
package org.tanuneko;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("org.tanuneko")
public class AppConfig {
@Bean
public NodeIF data() {
return new DataNode( "This is prod" );
}
}
App(非テスト用)
package org.tanuneko;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public App() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register( AppConfig.class );
ctx.refresh();
NodeIF node = ctx.getBean( DataNode.class );
System.out.println( node.getData() );
DataDumpService srv = ctx.getBean( ConsoleDataDumpService.class );
srv.dump( node.getData() );
}
public static void main( String args[] ) {
App a = new App();
}
}
テストアップランチャ
package org.tanuneko;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestAppLauncher {
@Autowired
DataDumpService dp;
@Autowired
NodeIF dataNode;
}
AppConfig(テスト用)
package org.tanuneko;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("org.tanuneko")
public class AppTestConfig {
@Bean
public NodeIF data() {
return new DataNode( "This is test" );
}
}
テストクラス
package org.tanuneko;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AppTest {
private static TestAppLauncher testApp;
@BeforeClass
public static void init() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register( AppTestConfig.class );
ctx.refresh();
testApp = ctx.getBean( TestAppLauncher.class );
}
@Test
public void testDataNode() {
testApp.dp.dump( testApp.dataNode.getData() );
}
}