JMockit - Невозможно привязать высмеянный класс к тестируемому классу

У меня есть приложение с 3 слоями: App <-> Graph <-> Couchbase

Я пытаюсь протестировать GraphConnector, высмеивая слой couchbase и "заменяя" его очень простой реализацией графа в памяти, используя тот же подход, который продемонстрирован в руководстве по JMockit.

Это мой тестовый класс (извините за плохой отступ, пока не освоил его):

public class GraphConnectorTest {
public static final class MockCouchbase extends MockUp<ICouchConnector> {
    private Map<String, CouchEntry> couch;

    @Mock
    public void $clinit() {
        couch = new HashMap<String, CouchEntry>();
    }

    @Mock
    public void put(CouchEntry entry) {
        couch.put(entry.getKey(), entry);
    }

    @Mock
    public CouchEntry get(String key) {
        return couch.get(key);
    }
}

GraphConnectorImpl graph = new GraphConnectorImpl();

@BeforeClass
public static void setUpClass() {
    new MockCouchbase();
}

@Test
public void testPost() throws Exception {
    GraphNode node = new GraphNode(GraphNodeType.DOMAIN, "alon.com");
    graph.post(node);
    GraphNode retNode = graph.getSingleNode(node.getValue(), node.getType());
    assertEquals(node.getValue(), retNode.getValue());
    assertEquals(node.getType(), retNode.getType());    
}
}

И вот мой тестируемый класс:

public class GraphConnectorImpl implements IGraphConnector {

private static ICouchConnector couch = new CouchConnectorImpl();  // <-- Basic implementation which I don't want the test to execute

@Override
public void post(GraphNode node) {
    CouchEntry entry = new CouchEntry(node.getValue(), JsonDocument.create(node.getValue()));
    couch.put(entry);
}

@Override
public GraphNode getSingleNode(String nodeName, GraphNodeType nodeType) {
    return new GraphNode(nodeType, couch.get(nodeName).getKey());
}
}

По какой-то причине класс MockCouchbase созданный в тестовом классе, автоматически не привязывается к закрытому полю ICouchConnector couch протестированного класса, как показано в руководстве. Вместо этого вызывается реальная реализация, что, очевидно, нежелательно.
Если я удалю ссылку на реальную реализацию, я просто получу хороший NullPointerException,
Я пытался играть с @Tested а также @Injectable аннотации, но безрезультатно.

1 ответ

Решение

Решаю свой вопрос.

Проблема с тем, как я написал тестируемый класс, заключалась в явном вызове конструктора реальной реализации. Я буду удивлен, может ли какая-то насмешливая структура "обойти" это.

Вместо этого я должен был создать конструктор, который получает ICouchConnector в качестве одного из аргументов, например, правильно использовать внедрение зависимостей.

public class GraphConnectorImpl implements IGraphConnector {
    private static ICouchConnector couch;

    public GraphConnectorImpl(ICouchConnector connector) {
        couch = connector;
    }
    // Rest of class...
}

Затем JMockit попытается найти конструктор, соответствующий аннотированным полям @Tested а также @Injectable в тестовом классе.

public class GraphConnectorTest {
    @Tested
    GraphConnectorImpl graph;

    @Injectable
    ICouchConnector couch;

    // Rest of class...
}
Другие вопросы по тегам