unit testing with wounit
TRANSCRIPT
Unit Testing with WOUnitHenrique Prange (HP)
• WOUnittest
• Wonder’s ERXTestCase
• JavaMemoryAdaptor
• Ad hoc Testing
History
Why another framework?
• Simple
• Fast
• Full support for Wonder features
• Concise assertions
• Test isolation
Features
• Use the new @Rule
• MockEditingContext extends ERXEditingContext
• Useful assertions for EOF logic
• Compatible with WOUnittest
Writing Tests
• MockEditingContext annotated with @Rule
• Load the required EOModels before running tests
• Clear the environment after running each test
• Prepare EOs
• Play with EOs
• Use assertions to verify behavior
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@Test public void cantSaveFooWithNullProperty() { Foo foo = ERXEOControlUtilities.createAndInsertObject(ec, Foo.class);
foo.setProperty(null);
confirm(foo, cannotBeSavedBecause("Foo must have a property")); }}
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@Test public void cantSaveFooWithNullProperty() { Foo foo = ERXEOControlUtilities.createAndInsertObject(ec, Foo.class);
foo.setProperty(null);
confirm(foo, cannotBeSavedBecause("Foo must have a property")); }
@Test public void canSaveFooWithNotNullProperty() { Foo foo = ERXEOControlUtilities.createAndInsertObject(ec, Foo.class);
foo.setProperty("bar");
confirm(foo, canBeSaved()); }}
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
private Foo foo;
@Before public void setup() { foo = ERXEOControlUtilities.createAndInsertObject(ec, Foo.class); }
@Test public void cantSaveFooWithNullProperty() { foo.setProperty(null);
confirm(foo, cannotBeSavedBecause("Foo must have a property")); }
@Test public void canSaveFooWithNotNullProperty() { foo.setProperty("bar");
confirm(foo, canBeSaved()); }}
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@UnderTest private Foo foo;
@Test public void cantSaveFooWithNullProperty() { foo.setProperty(null);
confirm(foo, cannotBeSavedBecause("Foo must have a property")); }
@Test public void canSaveFooWithNotNullProperty() { foo.setProperty("bar");
confirm(foo, canBeSaved()); }}
@UnderTest
• Behave as a real object
• All validations apply
• Alternative to createAndInsertObject
Assertions
• EOAssert class
• EO can/cannot be saved
• EO can/cannot be deleted
• EO has/hasn’t been saved
• EO has/hasn’t been deleted
• EC does/doesn’t save changes successfully
Dummy Objects
• Do not need to be initialized
• Because validations don’t apply
• @Dummy as alternative to ec.createSavedObject
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@UnderTest private Foo foo;
@Test public void canSaveFooWithBar() { Bar bar = ec.createSavedObject(Bar.class);
foo.setBar(bar);
confirm(foo, canBeSaved()); }}
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@UnderTest private Foo foo;
@Dummy private Bar bar;
@Test public void canSaveFooWithBar() { foo.setBar(bar);
confirm(foo, canBeSaved()); }}
NSArray of EOs
• Useful to test toMany relationships
• Work with @UnderTest and @Dummy
• EOs can be spied with @Spy
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@UnderTest private Foo foo;
@Dummy private Bar bar1, bar2, bar3, bar4;
@Test public void cannotSaveFooWithLessThanFiveBars() { foo.addToBarRelationship(bar1); foo.addToBarRelationship(bar2); foo.addToBarRelationship(bar3); foo.addToBarRelationship(bar4);
confirm(foo, cannotBeSaved()); }}
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@UnderTest private Foo foo;
@Dummy(size = 4) private NSArray<Bar> bars;
@Test public void cannotSaveFooWithLessThanFiveBars() { foo.addObjectsToBothSidesOfRelationshipWithKey(bars, Foo.BARS_KEY);
confirm(foo, cannotBeSaved()); }}
Restrictions
• No support for Properties
• No support for Localization
• No support for SQL operations
Spying Objects
• Useful to workaround WOUnit limitations
• Allows to change and verify behavior
• Requires Mockito
• @Spy as alternative to spy(new Foo) + insertObject
• Requires @RunWith(MockitoJUnitRunner.class)
Sampleclass FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@Test public void callSlowMethodWhenDoingSomething() { Foo foo = new Foo(); foo = Mockito.spy(foo); ec.insertObject(foo);
Mockito.doNothing().when(foo).slowMethodWithSideEffects();
foo.doSomething();
Mockito.verify(foo).slowMethodWithSideEffects(); }}
Sample@RunWith(MockitoJUnitRunner.class)class FooTest { @Rule public MockEditingContext ec = new MockEditingContext("MyModel");
@Spy @UnderTest private Foo foo;
@Test public void callSlowMethodWhenDoingSomething() { Mockito.doNothing().when(foo).slowMethodWithSideEffects();
foo.doSomething();
Mockito.verify(foo).slowMethodWithSideEffects(); }}
DEMO
Future
• Improved troubleshooting messaging
• Automatically load EOModels
• Fix for issue #20
License and Distribution• It’s free
• Apache 2 license
• Source and Binaries
• hprange.github.com/wounit
• github.com/hprange/wounit
• maven.wocommunity.org