/*
* Copyright (c) 2006 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import org.junit.*;
import static org.junit.Assert.*;
import mockit.internal.*;
public final class DynamicOnInstanceMockingTest
{
static class Collaborator
{
protected int value;
Collaborator() { value = -1; }
Collaborator(int value) { this.value = value; }
int getValue() { return value; }
void setValue(int value) { this.value = value; }
}
static class AnotherDependency
{
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
@Test
public void mockingOneInstanceAndMatchingInvocationsOnlyOnThatInstance()
{
Collaborator collaborator1 = new Collaborator();
Collaborator collaborator2 = new Collaborator();
final Collaborator collaborator3 = new Collaborator();
new Expectations(collaborator3) {{
collaborator3.getValue(); result = 3;
}};
assertEquals(-1, collaborator1.getValue());
assertEquals(-1, collaborator2.getValue());
assertEquals(3, collaborator3.getValue());
assertEquals(2, new Collaborator(2).getValue());
}
@Test
public void mockingTwoInstancesAndMatchingInvocationsOnEachOne()
{
final Collaborator collaborator1 = new Collaborator();
Collaborator collaborator2 = new Collaborator();
new Expectations(collaborator1, collaborator2) {{
collaborator1.getValue(); result = 1;
}};
collaborator2.setValue(2);
assertEquals(2, collaborator2.getValue());
assertEquals(1, collaborator1.getValue());
assertEquals(3, new Collaborator(3).getValue());
}
@Test
public void mockingAClassAndMatchingInvocationsOnAnyInstance()
{
final Collaborator collaborator = new Collaborator();
new Expectations(Collaborator.class) {{
collaborator.getValue(); result = 1;
}};
collaborator.setValue(2);
assertEquals(1, collaborator.getValue());
assertEquals(1, new Collaborator(2).getValue());
}
@Test
public void mockingOneInstanceButRecordingOnAnother()
{
Collaborator collaborator1 = new Collaborator();
final Collaborator collaborator2 = new Collaborator();
Collaborator collaborator3 = new Collaborator();
new Expectations(collaborator1) {{
// A misuse of the API:
collaborator2.getValue(); result = -2;
}};
collaborator1.setValue(1);
collaborator2.setValue(2);
collaborator3.setValue(3);
assertEquals(1, collaborator1.getValue());
assertEquals(-2, collaborator2.getValue());
assertEquals(3, collaborator3.getValue());
}
@Test
public void mockingOneInstanceAndOneClass()
{
Collaborator collaborator1 = new Collaborator();
final Collaborator collaborator2 = new Collaborator();
Collaborator collaborator3 = new Collaborator();
final AnotherDependency dependency = new AnotherDependency();
new Expectations(collaborator2, AnotherDependency.class) {{
collaborator2.getValue(); result = -2;
dependency.getName(); result = "name1";
}};
collaborator1.setValue(1);
collaborator2.setValue(2);
collaborator3.setValue(3);
assertEquals(-2, collaborator2.getValue());
assertEquals(1, collaborator1.getValue());
assertEquals(3, collaborator3.getValue());
dependency.setName("modified");
assertEquals("name1", dependency.getName());
AnotherDependency dep2 = new AnotherDependency();
dep2.setName("another");
assertEquals("name1", dep2.getName());
}
public static class Foo
{
Foo buildValue(@SuppressWarnings("unused") String s) { return this; }
boolean doIt() { return false; }
boolean doItAgain() { return false; }
AnotherDependency getBar() { return null; }
}
public static class SubFoo extends Foo {}
@Test
public void recordDuplicateInvocationOnTwoDynamicMocksOfDifferentTypesButSharedBaseClass()
{
final Foo f1 = new Foo();
final SubFoo f2 = new SubFoo();
new Expectations(f1, f2) {{
f1.doIt(); result = true;
f2.doIt(); result = false;
}};
assertTrue(f1.doIt());
assertFalse(f2.doIt());
assertFalse(new Foo().doIt());
assertFalse(new SubFoo().doIt());
}
@Test
public void passBothClassLiteralAndInstanceInExpectationsConstructor()
{
final Foo foo1 = new Foo();
Foo foo2 = new Foo();
// Instance-specific mocking takes precedence over any-instance mocking, when both are
// (erroneously) used for the same class.
new Expectations(Foo.class, foo1) {{
foo1.doIt(); result = true;
}};
assertTrue(foo1.doIt());
assertFalse(foo2.doItAgain());
assertFalse(foo2.doIt());
assertFalse(foo1.doItAgain());
Foo foo3 = new Foo();
assertFalse(foo3.doIt());
assertFalse(foo3.doItAgain());
}
@Test
public void verifyMethodInvocationCountOnMockedAndNonMockedInstances()
{
final Foo foo1 = new Foo();
final Foo foo2 = new Foo();
new Expectations(foo1, foo2) {{
foo1.doIt(); result = true;
}};
assertTrue(foo1.doIt());
assertFalse(foo2.doItAgain());
assertFalse(foo2.doIt());
final Foo foo3 = new Foo();
assertFalse(foo1.doItAgain());
assertFalse(foo3.doItAgain());
assertFalse(foo3.doIt());
assertFalse(foo3.doItAgain());
new Verifications() {{
assertFalse(foo2.doIt()); times = 1;
assertFalse(foo1.doItAgain()); times = 1;
assertFalse(foo3.doItAgain()); times = 2;
}};
}
@Test
public void createCascadedMockFromPartiallyMockedInstance()
{
final Foo foo = new Foo();
new Expectations(foo) {{
foo.getBar().getName(); result = "cascade";
}};
assertEquals("cascade", foo.getBar().getName());
}
@Test
public void useAvailableMockedInstanceAsCascadeFromPartiallyMockedInstance(@Mocked AnotherDependency bar)
{
final Foo foo = new Foo();
new Expectations(foo) {{
foo.getBar().getName(); result = "cascade";
}};
AnotherDependency cascadedBar = foo.getBar();
assertSame(bar, cascadedBar);
assertEquals("cascade", cascadedBar.getName());
}
static final class Bar extends AnotherDependency {}
@Test
public void useAvailableMockedSubclassInstanceAsCascadeFromPartiallyMockedInstance(@Mocked Bar bar)
{
final Foo foo = new Foo();
new Expectations(foo) {{
foo.getBar().getName(); result = "cascade";
}};
AnotherDependency cascadedBar = foo.getBar();
assertSame(bar, cascadedBar);
assertEquals("cascade", cascadedBar.getName());
}
@Test
public void useItselfAsCascadeFromPartiallyMockedInstance()
{
final Foo foo = new Foo();
new Expectations(foo) {{
foo.buildValue(anyString).doIt(); result = true;
}};
Foo cascadedFoo = foo.buildValue("test");
assertSame(foo, cascadedFoo);
assertTrue(cascadedFoo.doIt());
}
@Test
public void verifySingleInvocationToMockedInstanceWithAdditionalInvocationToSameMethodOnAnotherInstance()
{
final Collaborator mocked = new Collaborator();
new Expectations(mocked) {};
Collaborator notMocked = new Collaborator();
assertEquals(-1, notMocked.getValue());
assertEquals(-1, mocked.getValue());
new Verifications() {{
mocked.getValue();
times = 1;
}};
}
@Test(expected = MissingInvocation.class)
public void verifyOrderedInvocationsToDynamicallyMockedInstanceWithAnotherInstanceInvolvedButMissingAnInvocation()
{
final Collaborator mock = new Collaborator();
new Expectations(mock) {};
mock.setValue(1);
new Collaborator().setValue(2);
new VerificationsInOrder() {{
mock.setValue(1); times = 1;
mock.setValue(2); times = 1; // must be missing
}};
}
@Test
public void verifyOrderedInvocationsToDynamicallyMockedInstanceWithAnotherInstanceInvolved()
{
final Collaborator mock = new Collaborator();
new Expectations(mock) {{ mock.setValue(anyInt); }};
mock.setValue(1);
new Collaborator().setValue(2);
new VerificationsInOrder() {{
mock.setValue(1); times = 1;
mock.setValue(2); times = 0;
}};
}
static class Baz {}
static class Noop { void noop() {} }
@Test(expected = MissingInvocation.class)
public void partiallyMockClassWithInjectableMockWhileHavingTwoMockParametersOfAnotherType(
@Injectable final Noop mock, @Mocked Baz a, @Mocked Baz b)
{
Noop foo = new Noop();
new Expectations(Noop.class) {{ mock.noop(); }};
foo.noop();
}
}