【问题标题】:In testing in java how to check if a method of an interface is called or not?在java中测试如何检查接口的方法是否被调用?
【发布时间】:2014-07-22 12:26:37
【问题描述】:

我想测试这个使用匿名类调用接口方法的类。

public class ClassToTest 
{
    public void methodToTest()
    {
        InterefaceToMock interefaceToMockReference = new InterefaceToMock() {

            @Override
            public int methodToMock()
            {
                return 0;
            }
        };
        interefaceToMockReference.methodToMock();
    }
}

这是界面

public interface InterefaceToMock 
{
    public int methodToMock();
}

我正在使用这个方法来检查是否调用了 methodToMock

import static org.junit.Assert.*;

import org.junit.Test;

import mockit.FullVerificationsInOrder;
import mockit.Mocked;
import mockit.NonStrictExpectations;
public class TestAClass 
{
    @Mocked InterefaceToMock interefaceToMockReferenceMocked;
    @Test
    public void test1()
    {
        new NonStrictExpectations()
        {
            {
                interefaceToMockReferenceMocked.methodToMock();times=1;
            }
        };
        (new ClassToTest()).methodToTest();
        new FullVerificationsInOrder(interefaceToMockReferenceMocked)
        {
        };
        assertTrue(true);
    }
}

但是测试用例失败了。 谁能帮忙。

【问题讨论】:

  • 我不明白这里发生了什么。如果从未传入对实例的引用,ClassToTest.methodToTest() 如何调用 InterefaceToMock.methodToMock()
  • 它是如何失败的? AssertTrue(true) 永远不会失败。乱七八糟的代码。命名错误。
  • @BoristheSpider 使用匿名类对象调用。
  • @duffymo 验证失败。
  • 此处应删除期望记录块或期望验证块,因为在这种情况下您只需要一个。

标签: java unit-testing junit mocking jmockit


【解决方案1】:

您最初的测试几乎是正确的。它将模拟字段简单地声明为@Mocked,它只为您提供了一个实现接口的模拟实例,而这不是被测试代码使用的实例。然而,JMockit API 有另一个模拟注释,它将模拟从给定的基类型扩展到所有实现类,并且默认影响所述类的所有实例。所以,测试应该改变如下:

public class TestAClass 
{
    @Capturing InterfaceToMock anyImplementingInstance;

    @Test
    public void test1()
    {
        new ClassToTest().methodToTest();

        new Verifications() {{
            anyImplementingInstance.methodToMock();
        }};
    }
}

【讨论】:

  • 谢谢。你的答案是有效的。正如您在评论中建议的那样,我已经使用了这种方法,我应该使用期望验证块或期望记录块。 codeimport org.junit.Test;导入 mockit.Capturing;导入 mockit.NonStrictExpectations;公共类 TestAClass { @Capturing InterfaceToMock anyImplementingInstance; @Test public void test1() { new NonStrictExpectations() { { anyImplementingInstance.methodToMock();times=1; } };新的 ClassToTest().methodToTest(); } }code
  • 这个方法也有效。code new NonStrictExpectations() { @Capturing InterfaceToMock anyImplementingInstance; { anyImplementingInstance.methodToMock();times=1; } };code 我可以用这个方法吗?因为我不希望 InterfaceToMock 在其他测试方法中被嘲笑。
  • 不,不再支持本地模拟字段。您应该使用模拟 parameters 进行仅限于单个测试的模拟。
  • Maven 不支持在测试用例中传递参数。
  • 不,但是 JMockit 可以;试试看(为了清楚起见,我的意思是测试方法参数)。
【解决方案2】:

在一般情况下,如果您有一个class,并且您想检查该Mock 上的某个方法是否被调用,那么您可以使用Mockito.verify

例如:

public class AppTest {
    @Test
    public void testMe() {
        final ITest iTest = Mockito.mock(ITest.class);
        final CUT cut = new CUT(iTest);
        cut.doStuff();
        Mockito.verify(iTest).someStuff();
    }

    interface ITest {
        void someStuff();
    }

    class CUT {
        private final ITest iTest;

        CUT(ITest iTest) {
            this.iTest = iTest;
        }

        public void doStuff() {
            iTest.someStuff();
        }
    }
}

这里测试的是ITest.someStuff()是否被CUT.doStuff()调用。

你的例子是无法辨认的......

【讨论】:

  • 感谢您的支持。如您所见,我无法将模拟实例传递给我正在测试的类。像这样“最终 CUT cut = new CUT(iTest);”请根据给定的例子提供答案。我必须使用 JMockit。我不能使用任何其他模拟框架工作。这是一个限制。如果您无法理解示例中的任何内容,请务必询问不清楚的地方。
猜你喜欢
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 2016-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多