make it test-driven with cdi!

27
Make it test-driven with CDI! Rafael Liu

Upload: rafaelliu

Post on 27-Nov-2014

4.782 views

Category:

Technology


1 download

DESCRIPTION

Palestra do Devoxx 2011 Antuérpia - Bélgica, 17/11/2011

TRANSCRIPT

Page 1: Make it test-driven with CDI!

Make it test-driven with CDI!

Rafael Liu

Page 2: Make it test-driven with CDI!

2

the red

Page 3: Make it test-driven with CDI!

3

Runtime environment

Page 4: Make it test-driven with CDI!

4

Test environment

Page 5: Make it test-driven with CDI!

5

Unit test

Page 6: Make it test-driven with CDI!

6

What about...

● Access level modifiers limitations?● Injection uses reflection

● “Unit” related stuff?● Bean lifecycle (@PostConstruct, @PreDestroy)● Interceptors / Decorators● Events

Page 7: Make it test-driven with CDI!

7

Integration test

Page 8: Make it test-driven with CDI!

8

the green(s)

Page 9: Make it test-driven with CDI!

9

1. CDI @Alternatives

● Typesafe bean resolution● Abstraction + implementation

● “Real” implementation● Mock implementation

● Runtime vs. test classpath● beans.xml

Page 10: Make it test-driven with CDI!

10

Extracting an interface

Page 11: Make it test-driven with CDI!

11

Creating a mock @Alternative

Page 12: Make it test-driven with CDI!

12

The classpath magic

Page 13: Make it test-driven with CDI!

13

2. Arquillian

● JBoss Testing initiative● Test enrichment● Inside-container testing

● JBoss AS 5 and 6● GlassFish 3● Tomcat 6● Jetty 6 and 7

Page 14: Make it test-driven with CDI!

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);      }}

Page 15: Make it test-driven with CDI!

15

The Arquillian way

Page 16: Make it test-driven with CDI!

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

Page 17: Make it test-driven with CDI!

17

But...

● Still a class per mock● Various @Deployments● The single implementation dilema● We can't use mock frameworks anymore!

Page 18: Make it test-driven with CDI!

18

refactoring

Page 19: Make it test-driven with CDI!

19

What we want?

Page 20: Make it test-driven with CDI!

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!

Page 21: Make it test-driven with CDI!

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;   }

}

Page 22: Make it test-driven with CDI!

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")));   }

}

Page 23: Make it test-driven with CDI!

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"));   }

}

Page 24: Make it test-driven with CDI!

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!

Page 25: Make it test-driven with CDI!

25

Fork me!

http://github.com/rafaelliu

Page 26: Make it test-driven with CDI!

26

Questions?

@rafaelliu

http://rafaelliu.net

Page 27: Make it test-driven with CDI!

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)