Skip to content

Instantly share code, notes, and snippets.

@jnericks
Created July 15, 2015 18:22
Show Gist options
  • Save jnericks/6567986b1785af171aa1 to your computer and use it in GitHub Desktop.
Save jnericks/6567986b1785af171aa1 to your computer and use it in GitHub Desktop.
SystemUnderTestFactory.java
package com.jnericks.testutils;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.*;
import java.util.function.Supplier;
import static org.mockito.Mockito.*;
@SuppressWarnings("unchecked")
public abstract class SystemUnderTestFactory<TSut>
{
private final Class<TSut> _type;
private volatile Constructor<?> _ctor;
private ArrayList _dependencies;
private TSut _sut;
private Runnable _preProcessor;
private Supplier<TSut> _sutFactory;
private Consumer<TSut> _postProcessor;
public SystemUnderTestFactory()
{
ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
_type = (Class<TSut>) superclass.getActualTypeArguments()[0];
_dependencies = new ArrayList();
_ctor = getGreediestCtor();
Class[] parameterTypes = _ctor.getParameterTypes();
for (Class cls : parameterTypes)
{
_dependencies.add(mock(cls));
}
}
public void createSutUsing(Supplier<TSut> sutFactory)
{
_sutFactory = sutFactory;
}
public void beforeSutCreated(Runnable preProcessor)
{
_preProcessor = preProcessor;
}
public void afterSutCreated(Consumer<TSut> postProcessor)
{
_postProcessor = postProcessor;
}
public void createSut()
{
try
{
if (_sut == null)
{
if (_preProcessor != null)
_preProcessor.run();
if (_sutFactory == null)
_sut = (TSut) _ctor.newInstance(_dependencies.toArray());
else
_sut = _sutFactory.get();
if (_postProcessor != null)
_postProcessor.accept(_sut);
}
} catch (IllegalAccessException | InvocationTargetException | InstantiationException ignored) { }
}
public TSut sut()
{
createSut();
return _sut;
}
public <TDependency> TDependency dependency(Class<TDependency> type)
{
for (Object o : _dependencies)
{
if (type.isAssignableFrom(o.getClass()))
{
return (TDependency) o;
}
}
throw new UnsupportedOperationException(String
.format("%s is not a dependency of %s", type.getSimpleName(), _type.getSimpleName()));
}
public <TDependency> DoForDependency<TDependency> forDependency(Class<TDependency> type)
{
for (int i = 0; i < _dependencies.size(); i++)
{
if (type.isAssignableFrom(_dependencies.get(i).getClass()))
{
return new DoForDependency(type, _dependencies, i);
}
}
throw new UnsupportedOperationException(String
.format("%s is not a dependency of %s", type.getSimpleName(), _type.getSimpleName()));
}
Constructor getGreediestCtor()
{
Constructor[] ctors = _type.getConstructors();
Constructor greediest = ctors[0];
int count = greediest.getParameterCount();
int len = ctors.length;
if (len > 1)
{
for (int i = 1; i < len; i++)
{
Constructor ctor = ctors[i];
if (ctor.getParameterCount() > count)
{
greediest = ctor;
count = ctor.getParameterCount();
}
}
}
return greediest;
}
public class DoForDependency<TDoFor>
{
final Class<TDoFor> _type;
ArrayList _dependencies;
int _index;
protected DoForDependency(Class<TDoFor> type, ArrayList dependencies, int index)
{
_type = type;
_dependencies = dependencies;
_index = index;
}
public void use(TDoFor dependency)
{
_dependencies.set(_index, dependency);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment