简体   繁体   English

JMockit-无法将模拟类绑定到测试类

[英]JMockit - Can't bind mocked class to tested class

I have an application with 3 layers: App <--> Graph <--> Couchbase 我有一个包含三层的应用程序:App <->图形<-> Couchbase

I'm trying to test the GraphConnector by mocking the couchbase layer and "replacing" it with a very basic in-memory graph implementation, using the same approach demonstrated in the JMockit tutorial . 我正在尝试通过模拟Couchbase层并使用非常基本的内存中图实现“替换”它来测试GraphConnector,使用JMockit 教程中演示的相同方法。

This is my test class (pardon the poor indentation, didn't get the hang of it yet): 这是我的测试课(请原谅可怜的缩进,还没有掌握):

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());    
}
}

And here is my class under test: 这是我的课程正在测试:

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());
}
}

For some reason, the class MockCouchbase that I created within the test class isn't automatically bound to the private field ICouchConnector couch of the tested class, as shown in the tutorial. 由于某种原因,我在测试类中创建的类MockCouchbase不会自动绑定到测试类的专用字段ICouchConnector couch ,如本教程所示。 Instead, the real implementation is called, which is obviously undesirable. 而是调用了真正的实现,这显然是不可取的。
If I remove the reference to the real implementation, I just get a good ol' NullPointerException . 如果删除对实际实现的引用,我将得到一个很好的NullPointerException
I tried playing with the @Tested and @Injectable annotations but to no avail. 我尝试使用@Tested@Injectable批注,但无济于事。

Solving my own question. 解决我自己的问题。

The problem with the way I wrote the class under test was explicitly invoking the constructor of the real implementation. 我编写被测类的方式的问题是显式调用实际实现的构造函数。 I'll be surprised if any mocking framework can "bypass" that. 如果任何模拟框架都可以“绕过”它,我会感到惊讶。

Instead, I should've created a constructor that gets ICouchConnector as one of its arguments, eg use dependency injection properly. 相反,我应该创建一个构造函数,将ICouchConnector作为其参数之一,例如,正确使用依赖项注入。

public class GraphConnectorImpl implements IGraphConnector {
    private static ICouchConnector couch;

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

JMockit will then attempt to find a constructor that corresponds to the fields annotated @Tested and @Injectable in the test class. 然后,JMockit将尝试查找与测试类中带注释的@Tested@Injectable字段相对应的构造函数。

public class GraphConnectorTest {
    @Tested
    GraphConnectorImpl graph;

    @Injectable
    ICouchConnector couch;

    // Rest of class...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM