package org.testory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
import static org.testory.Testory.given;
import static org.testory.Testory.mock;
import static org.testory.Testory.willReturn;
import static org.testory.Testory.willThrow;
import static org.testory.testing.Fakes.newObject;
import static org.testory.testing.Fakes.newThrowable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.testory.proxy.Handler;
import org.testory.proxy.Invocation;
import org.testory.proxy.InvocationMatcher;
public class TestStubbing {
private Object object, otherObject;
private Throwable throwable;
private Invocation invocation;
private InvocationMatcher onAlways, onNever, invocationMatcher;
private Handler handler;
private Mockable mock;
@Before
public void before() {
object = newObject("object");
otherObject = newObject("otherObject");
throwable = newThrowable("throwable");
onAlways = new InvocationMatcher() {
public boolean matches(Invocation inv) {
return true;
}
};
onNever = new InvocationMatcher() {
public boolean matches(Invocation inv) {
return false;
}
};
invocationMatcher = mock(InvocationMatcher.class);
handler = mock(Handler.class);
mock = mock(Mockable.class);
given(willThrow(new RuntimeException("unstubbed")), onAlways);
}
@Test
public void mock_returns_object() {
given(willReturn(object), onAlways);
assertSame(object, mock.returnObject());
}
@Test
public void mock_returns_primitive() {
given(willReturn(5), onAlways);
assertEquals(5, mock.returnInt());
}
@Test
public void mock_returns_null() {
given(willReturn(null), onAlways);
assertEquals(null, mock.returnObject());
}
@Test
public void mock_returns_void() {
given(willReturn(null), onAlways);
mock.returnVoid();
}
@Test
public void mock_throws_error() {
throwable = new Error();
given(willThrow(throwable), onAlways);
try {
mock.returnObject();
fail();
} catch (Throwable t) {
assertSame(throwable, t);
}
}
@Test
public void mock_throws_runtime_exception() {
throwable = new RuntimeException();
given(willThrow(throwable), onAlways);
try {
mock.returnObject();
fail();
} catch (Throwable t) {
assertSame(throwable, t);
}
}
@Test
public void mock_throws_declared_throwable() {
given(willThrow(throwable), onAlways);
try {
mock.throwThrowable();
fail();
} catch (Throwable t) {
assertSame(throwable, t);
}
}
@Test
public void mock_throws_declared_exception() {
throwable = new IOException();
given(willThrow(throwable), onAlways);
try {
mock.throwIOException();
fail();
} catch (Throwable t) {
assertSame(throwable, t);
}
}
@Test
public void mock_throws_subclass_of_declared_exception() {
throwable = new FileNotFoundException();
given(willThrow(throwable), onAlways);
try {
mock.throwIOException();
fail();
} catch (Throwable t) {
assertSame(throwable, t);
}
}
@Test
public void stubbing_cannot_return_super_type() {
given(willReturn(object), onAlways);
try {
mock.returnString();
fail();
} catch (TestoryException e) {}
}
@Test
public void stubbing_cannot_return_wider_primitive() {
given(willReturn(3f), onAlways);
try {
mock.returnInt();
fail();
} catch (TestoryException e) {}
}
@Test
public void stubbing_cannot_return_object_as_void() {
given(willReturn(object), onAlways);
try {
mock.returnVoid();
fail();
} catch (TestoryException e) {}
}
@Test
public void stubbing_cannot_return_object_as_primitive() {
given(willReturn(object), onAlways);
try {
mock.returnInt();
fail();
} catch (TestoryException e) {}
}
@Test
public void stubbing_cannot_return_null_as_primitive() {
given(willReturn(null), onAlways);
try {
mock.returnInt();
fail();
} catch (TestoryException e) {}
}
@Test
public void stubbing_cannot_not_throw_undeclared_exception() {
throwable = new IOException();
given(willThrow(throwable), onAlways);
try {
mock.returnObject();
fail();
} catch (TestoryException t) {}
}
@Test
public void stubbing_cannot_throw_undeclared_throwable() {
given(willThrow(throwable), onAlways);
try {
mock.returnObject();
fail();
} catch (TestoryException e) {}
}
@Test
public void stubbing_cannot_throw_superclass_of_declared_exception() throws IOException {
throwable = new Exception();
given(willThrow(throwable), onAlways);
try {
mock.throwIOException();
fail();
} catch (TestoryException t) {}
}
@Test
public void mock_uses_last_stubbing() {
given(willReturn(object), onAlways);
given(willReturn(otherObject), onAlways);
assertSame(otherObject, mock.returnObject());
}
@Test
public void mock_uses_last_matching_stubbing() {
given(willReturn(object), onAlways);
given(willReturn(otherObject), onNever);
assertSame(object, mock.returnObject());
}
@Test
public void mock_does_not_use_stubbing_preceding_its_creation() {
given(willReturn(object), onAlways);
mock = mock(Mockable.class);
assertNotSame(object, mock.returnObject());
}
@Test
public void invocation_matcher_matches_invocation_on_mock() throws NoSuchMethodException {
given(new Handler() {
public Object handle(Invocation inv) {
invocation = inv;
return null;
}
}, onAlways);
mock.acceptObject(object);
assertSame(mock, invocation.instance);
assertEquals(Mockable.class.getDeclaredMethod("acceptObject", Object.class), invocation.method);
assertEquals(Arrays.asList(object), invocation.arguments);
}
@Test
public void checks_that_invocation_matcher_is_not_null() {
try {
given(handler, (InvocationMatcher) null);
fail();
} catch (TestoryException e) {}
}
@Test
public void checks_that_handler_is_not_null() {
try {
given(null, invocationMatcher);
fail();
} catch (TestoryException e) {}
}
private static abstract class Mockable {
abstract Object returnObject();
abstract String returnString();
abstract int returnInt();
abstract void returnVoid();
abstract void throwThrowable() throws Throwable;
abstract void throwIOException() throws IOException;
abstract Object acceptObject(Object argument);
}
}