java - java中测试数据库类

标签 java unit-testing junit mockito powermock

我有一个类,它执行基本的数据库操作,例如在数据库中保存、检索和删除对象。它有一个在每次操作之前调用的 assessConnection() 方法。

我还有另一个类,它从 DB 类调用 saveObject 方法来存储它创建的图形(如果它在 getter 中返回之前不存在)。为了测试这个 setter/getter ,我尝试了junit,但它在存储对象的部分失败,并在我第一次设置图表然后尝试检索它时给出java.lang.ExceptionInInitializerError,但是当我调用时getter 没有先设置图表,以便创建图表,然后我得到一个 java.lang.NoClassDefFoundError 。我需要通过单元测试来测试这两个类,但我找不到任何简单的示例。

数据库类概要:

public final class DbUtils {

    private static Connection connectionDB;

    private static void establishConnection() { 
     ...
    }

    private static void closeConnection() {
     ... 
    }

    public static void saveObject(final Object graph, final Object map) {

        establishConnection();

        //convert Objects to Byte and store it;

        closeConnection();
    }

    public static Map<String, Object> retrieveObject(final String key) {
        establishConnection();
        //read byte and convert to object
        closeConnection();
        return multireturn;
    }

    public static boolean deleteObject(final String key) {
        establishConnection();
        //delete all object except object with key
        closeConnection();
        return (affectedRow >= 1);

    }

}

GraphCreation类:

public class GraphCreation {
    Graph graph;
    ...
    private createGraph(){....}

    public void setGraph(Graph G){
        this.graph=G;
    }

    public Graph getGraph(){
        if(this.graph==null){
            createGraph();
        }
        saveToDB(graph, map);
        return this.graph
    }

}

当前测试:

@Mock
GraphCreation graph;

@Test
public void testSettingDependencyGraph() {
    graphCreation.setGraph(graph);
    Assert.assertEquals(Graph, graphCreation.getGraph());
}

@Test
public void testCreatingGraph(){
    graphCreation.setApplicationContext(applicationContext);
    graphCreation.setGraph(new Graph());
    moduleRegistrationBeans = new HashMap<String, ModuleRegistration>();
    ModuleRegistration m1 = new ModuleRegistration();
    m1.setName("module1");
    SDF1 = new TestSourceDataFactoryTemplate();
    VM1 = new TestModuleTemplate();
    m1.setSourceDataFactory(SDF1);
    m1.setModule(VM1);
    moduleRegistrationBeans.put("module_1", m1);
    PowerMock.reset(BeanFactoryUtils.class);
    PowerMock.mockStatic(BeanFactoryUtils.class);
    EasyMock.expect(BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleRegistration.class)).andReturn(moduleRegistrationBeans);
    PowerMock.replay(BeanFactoryUtils.class);
    graphCreation.getDependencyGraph();
}

这两个测试均在 GraphCreation 类中的 saveToDB() 方法处失败。 我是单元测试的新手,这些测试是由其他开发人员编写的,我添加了数据库功能,但现在单元测试失败了。 有人可以帮助我或指导我如何解决这个问题并为数据库类创建单元测试。

最佳答案

看起来你的负担过重;或者反过来:你尝试做很多事情......但不太了解自己在做什么。

首先:DbUtils静态方法。这是一项“直接”的任务,但有一些微妙的事情需要做好。如果你在那里搞砸了,那就根本行不通。因此:您必须严格遵循 here 概述的所有步骤.

但更重要的是:你不明白模拟的本质是什么。含义 - 这里:

@Mock
GraphCreation graph;

一起

graphCreation.setApplicationContext(applicationContext);
graphCreation.setGraph(new Graph());
...

根本没有任何意义。

当您告诉 Mockito(或 PowerMock,或任何其他框架)模拟一个类时,您就创建了一个模拟。该模拟仅“看起来”属于被测试的类别;但它只不过是一个“空壳”。该对象与您的生产代码没有任何关系。换句话说:像您一样在该模拟对象上调用方法是无操作。这没有实现任何有用的东西!

相反:您使用new实例化被测类的对象!也许您为该“真实”对象提供模拟对象;因为真实的对象需要单元测试环境中的那些模拟的东西。然后你调用真实对象的方法;然后你“断言”结果;或者您可以验证提供给真实对象的模拟是否看到了您期望看到的方法调用。

长话短说:退后一步,阅读如何正确进行单元测试,以及模拟如何发挥作用。开始阅读 here .

除此之外:到处使用静态方法是不好的做法。您应该认真考虑用非静态版本替换该解决方案(或者至少:在静态类周围放置一个包装器)。因为这样您就可以无需 PowerMock 进行测试。

最后:NoClassDefFoundError 表明您正在尝试运行某些内容...但是您的类路径设置中缺少一个/多个必需的类。可能是因为你 mock 错了。

但重点是:放慢速度;并了解您想做什么。而不是构建一个巨大而复杂的问题,该问题实际上由许多对您正在做的事情的微妙的不了解码成。

关于java - java中测试数据库类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43900007/

相关文章:

java - JMapViewer,绘制到OSM并避免两次调用MouseClick事件

Java 参数传递问题

c# - 用于单元测试的 ControllerContext.HttpContext 初始化

c# - Visual Studio 2015 测试运行器中的 "The handle is invalid"异常

java - 使用 EasyMock 或 Mockito 模拟 void 方法的 try catch block 并捕获异常

java - 获取子进程id

javascript - 使用 Jasmine 访问 js 模块的方法,以便可以单独测试它们

java - 重载参数化测试运行器不与 JUnit4Provider 一起工作

JUnit:无法模拟 RestTemplate 对象来调用 postForObject 方法

java - 如何在 Java 中创建数学序列?