/*
* Copyright (c) 2006-2011 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import java.sql.*;
import java.util.concurrent.atomic.*;
import org.junit.*;
import static org.junit.Assert.*;
public final class MockUpTest
{
static final class Collaborator
{
final boolean b;
Collaborator() { b = false; }
Collaborator(boolean b) { this.b = b; }
int doSomething(String s) { return s.length(); }
@SuppressWarnings({"UnusedDeclaration"})
<N extends Number> N genericMethod(N n) { return null; }
}
@Test
public void mockUpClass() throws Exception
{
new MockUp<Collaborator>()
{
@Mock(invocations = 1)
void $init(boolean b)
{
assertTrue(b);
}
@Mock(minInvocations = 1)
int doSomething(String s)
{
assertEquals("test", s);
return 123;
}
};
assertEquals(123, new Collaborator(true).doSomething("test"));
}
@Test
public void mockUpInterface() throws Exception
{
ResultSet mock = new MockUp<ResultSet>()
{
@Mock
boolean next() { return true; }
}.getMockInstance();
assertTrue(mock.next());
}
@Test
public <M extends Runnable & ResultSet> void mockUpTwoInterfacesAtOnce() throws Exception
{
M mock = new MockUp<M>()
{
@Mock(invocations = 1)
void run() {}
@Mock
boolean next() { return true; }
}.getMockInstance();
mock.run();
assertTrue(mock.next());
}
static final class Main
{
static final AtomicIntegerFieldUpdater<Main> atomicCount =
AtomicIntegerFieldUpdater.newUpdater(Main.class, "count");
volatile int count;
int max = 2;
boolean increment()
{
while (true) {
int currentCount = count;
if (currentCount >= max) {
return false;
}
if (atomicCount.compareAndSet(this, currentCount, currentCount + 1)) {
return true;
}
}
}
}
@Test
public void mockUpGivenClass()
{
final Main main = new Main();
AtomicIntegerFieldUpdater<?> atomicCount =
Deencapsulation.getField(Main.class, AtomicIntegerFieldUpdater.class);
new MockUp<AtomicIntegerFieldUpdater<Main>>(atomicCount.getClass())
{
boolean second;
@Mock(invocations = 2)
public boolean compareAndSet(Object obj, int expect, int update)
{
assertSame(main, obj);
assertEquals(0, expect);
assertEquals(1, update);
if (second) {
return true;
}
second = true;
return false;
}
};
assertTrue(main.increment());
}
@Test
public void mockGenericMethod()
{
new MockUp<Collaborator>()
{
@Mock <T extends Number> T genericMethod(T t) { return t; }
// This also works (same erasure):
// @Mock Number genericMethod(Number t) { return t; }
};
Integer n = new Collaborator().genericMethod(123);
assertEquals(123, n.intValue());
Long l = new Collaborator().genericMethod(45L);
assertEquals(45L, l.longValue());
Short s = new Collaborator().genericMethod((short) 6);
assertEquals(6, s.shortValue());
Double d = new Collaborator().genericMethod(0.5);
assertEquals(0.5, d, 0);
}
public static final class GenericClass<T>
{
public void methodWithGenericParameter(T t) { System.out.println("t=" + t); }
}
@Ignore @Test
public void mockMethodWithGenericTypeArgument()
{
// Currently, this isn't supported but it can be. If the mock method has a generic signature,
// then it can be used when comparing to real methods. The MockUp class can pass the type
// arguments ("StringBuilder") defined for "MockUp<T>".
new MockUp<GenericClass<StringBuilder>>()
{
@Mock
public void methodWithGenericParameter(StringBuilder s)
{
s.setLength(0);
s.append("mock");
}
};
StringBuilder s = new StringBuilder("test");
new GenericClass<StringBuilder>().methodWithGenericParameter(s);
assertEquals("mock", s.toString());
}
public interface GenericInterface<T> { void method(T t); }
public interface ConcreteInterface extends GenericInterface<Long> {}
@Ignore @Test
public void mockMethodOfSubInterfaceWithGenericTypeArgument()
{
ConcreteInterface mock = new MockUp<ConcreteInterface>()
{
@Mock(invocations = 1)
public void method(Long l)
{
assertTrue(l > 0);
}
}.getMockInstance();
mock.method(123L);
}
}