make it test-driven with cdi!
DESCRIPTION
Palestra do Devoxx 2011 Antuérpia - Bélgica, 17/11/2011TRANSCRIPT
Make it test-driven with CDI!
Rafael Liu
2
the red
3
Runtime environment
4
Test environment
5
Unit test
6
What about...
● Access level modifiers limitations?● Injection uses reflection
● “Unit” related stuff?● Bean lifecycle (@PostConstruct, @PreDestroy)● Interceptors / Decorators● Events
7
Integration test
8
the green(s)
9
1. CDI @Alternatives
● Typesafe bean resolution● Abstraction + implementation
● “Real” implementation● Mock implementation
● Runtime vs. test classpath● beans.xml
10
Extracting an interface
11
Creating a mock @Alternative
12
The classpath magic
13
2. Arquillian
● JBoss Testing initiative● Test enrichment● Inside-container testing
● JBoss AS 5 and 6● GlassFish 3● Tomcat 6● Jetty 6 and 7
14
A code is worth a thousand words@RunWith(Arquillian.class)public class TemperatureConverterTest {
@Inject private TemperatureConverter converter;
@Deployment public static JavaArchive createTestArchive() { return ShrinkWrap.create(JavaArchive.class, "test.jar") .addClasses(TemperatureConverter.class) .addAsManifestResource( EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml")); }
@Test public void testConvertToCelsius() { Assert.assertEquals(converter.convertToCelsius(32d), 0d); Assert.assertEquals(converter.convertToCelsius(212d), 100d); }}
15
The Arquillian way
16
Nice!
● We can check state● More meaningful units, the CDI beans!
● A one unit integration test
● Mocks can replace beans easily● Custom builds
● Descriptors and classes
17
But...
● Still a class per mock● Various @Deployments● The single implementation dilema● We can't use mock frameworks anymore!
18
refactoring
19
What we want?
20
Write a portable extension!
● Choose certain injection points● Resolve beans to custom mocks● Define mocks at runtime● Power of mock frameworks
● Thanks to our clever Expert Group!
21
A “real” case@Namedpublic class MyBean {
@Inject private MyDependency myDependency;
public String calculate(int a, int b) { return "multiplication is " + myDependency.multiply(a, b); }
}
@Namedpublic class MyDependency {
public int multiply(int a, int b) { return a*b; }
}
22
A code is worth.. you knowpublic class MyTest extends WeldMockTest { @Test public void testMock() { mockContext.addExpectations(new Expectations<MyDependency>() { @Override public void defineExpectations(MyDependency mock) { when(mock.multiply(2, 3)).thenReturn(5); } }); MyBean bean = getBean(MyBean.class);
String calculate = bean.calculate(2, 3); assertThat(calculate, is("multiplication is 5"));
calculate = bean.calculate(2, 4); assertThat(calculate, is(not("multiplication is 8"))); }
}
23
And a spypublic class MyTest extends WeldMockTest { @Test public void testSpy() { mockContext.addExpectations(DoubleType.SPY, new Expectations<MyDependency>() {
@Override public void defineExpectations(MyDependency mock) { when(mock.multiply(2, 3)).thenReturn(5); } }); MyBean bean = getBean(MyBean.class);
String calculate = bean.calculate(2, 3); assertThat(calculate, is("multiplication is 5"));
calculate = bean.calculate(2, 4); assertThat(calculate, is("multiplication is 8")); }
}
24
What we get
● It's an extension● Arquillian friendly● Can easy the pain of @Deployments
● Mock frameworks and all their greatness!● Choose precisely where to meddle
● Fine grained integration test
● Get a hold of your test code base!
25
Fork me!
http://github.com/rafaelliu
26
Questions?
@rafaelliu
http://rafaelliu.net
27
References● http://tinyurl.com/5mjgc8(http://code.google.com/p/mockito)
● http://tinyurl.com/cxshm2f(http://seamframework.org/Weld)
● http://tinyurl.com/c8qdtx8(http://monografias.cic.unb.br/dspace/bitstream/123456789/258/1/monografia.pdf)