0

[10/7/06 4:00 编辑的示例代码] 我正在尝试在不接触数据库的情况下测试一些代码(使用 JMockIt 和 TestNG),但看起来实际上仍然调用了一个模拟方法。这是简化的设置:

class DBRow {
    public DBRow() { }
    public DBRow(Object obj) {
        initialize(obj);
    }
    public void insert() {
        actuallyAddRowToDatabase();
    }
}

class MyObject extends DBRow {
    MyObject(Object obj) {
        super(obj);
    }
    public void insert(Object obj) {
        doSomething(obj);
        insert();
    }
}

class Factory {
    static MyObject createObject(Object obj1, Object obj2) {
        MyObject newObj = new MyObject(obj1);
        newObj.insert(obj2);
        return newObj;
    }
}

我想模拟插入操作以防止在实际数据库中插入,所以我尝试了这样的事情:

@Test
public void testCreation() {
    new Expectations(MyObject.class) {
        MyObject mock = new MyObject(null) {
            @Mock
            public void insert(Object obj) { }
        };
    {
        new MyObject(anyString);   result = mock;
    }};

    MyObject test = Factory.createObject("something", "something else");
}

但似乎真实insert(Object)的仍在被调用。我指定类是模拟的,所以所有的实例都应该被模拟,对吧?而且我指定应该模拟插入方法,那么为什么要调用真正的方法呢?

上面还有第二个问题。当我在 Expectations 块内定义模拟类(如上)时,似乎只Row()调用了构造函数而不是Row(Object),因此对象未正确初始化。我通过将它移动到一个@BeforeTest方法中并在那里实例化类来解决这个问题。看起来是这样的:

private MyObject mock;

@BeforeTest
public void beforeTest() {
    new MockUp<MyObject>() {
        @Mock
        public void insert(Object obj) { }
    };
    mock = new MyObject("something");
}

@Test
public void testCreation() {
    new Expectations(MyObject.class) {{
        new MyObject(anyString);   result = mock;
    }};

    MyObject test = Factory.createObject("something", "something else");
}

所以这似乎得到了正确的构造函数被调用,但它似乎仍然insert()被调用。有什么见解吗?

4

2 回答 2

0

我终于能够编写测试,以便调用正确的构造函数并且没有发生实际的数据库操作。我认为我遇到的部分问题是 Expectations 块中的一种方法得到的对象与我对我不感兴趣的参数的预期不同。而且我认为我的问题的另一部分是混淆了MockUp 类和期望记录的角色。

被测代码没有改变。为方便起见,这是我的简化示例:

class DBRow {
    public DBRow() { }
    public DBRow(Object obj) {
        initialize(obj);
    }
    public void insert() {
        actuallyAddRowToDatabase();
    }
}

class MyObject extends DBRow {
    MyObject(Object obj) {
        super(obj);
    }
    public void insert(Object obj) {
        doSomething(obj);
        insert();
    }
}

class Factory {
    static MyObject createObject(Object obj1, Object obj2) {
        MyObject newObj = new MyObject(obj1);
        newObj.insert(obj2);
        return newObj;
    }
}

这基本上是我最终得到的测试代码:

Object something;
Object somethingElse;

@BeforeTest
public void beforeTest() {
    new MockUp<MyObject>() {
        @Mock
        public void insert() { }  // override the "actual" DB insert
    };                            // of Row.insert()
}

@Test
public void testCreation() {
    MyObject mock = new MyObject(something);  // object correctly init'd
                                              // by Row.initialize(Object)
    new Expectations(MyObject.class) {{
        new MyObject(something);     result = mock;
        mock.insert(somethingElse);
    }};

    MyObject test = Factory.createObject(something, somethingElse);
}

关键点是 A) 我创建了一个 MockUp 类来覆盖数据库操作,并且 B) 创建了该部分模拟实例的本地实例来记录我的期望。

于 2016-10-10T20:10:46.680 回答
0

您不是使用模拟对象来调用您的功能,即private MyObject mock;,而是一个真实的对象test

MyObject test = new MyObject("something", "something else");

调用testStuff()mock不是test.

所有实例都不会被自动模拟,您必须使用模拟实例。

于 2016-10-07T19:10:37.183 回答