Java模拟-用模拟对象动态替换类

Java模拟-用模拟对象动态替换类,java,unit-testing,mocking,Java,Unit Testing,Mocking,我希望在运行时用mock替换类的所有实例。这可能吗?例如,在一个测试中,我想将classbar标记为模拟类。在测试范围内,在类Foo的构造函数中,newbar()应该返回Bar的模拟实例,而不是真正的类 class Bar { public int GiveMe5() { return 5; } } public class Foo { private Bar bar; Foo() { bar = new Bar();

我希望在运行时用mock替换类的所有实例。这可能吗?例如,在一个测试中,我想将
classbar
标记为模拟类。在测试范围内,在
类Foo
的构造函数中,
newbar()
应该返回
Bar
的模拟实例,而不是真正的类

class Bar {
    public int GiveMe5() {
        return 5;
    }
}

public class Foo {
    private Bar bar;

    Foo() {
        bar = new Bar();
    }
}
然后在我的测试中:

class TestFoo {
    @Before
    public void setUp() {
        // Tell the mocking framework every instance of Bar should be replaced with a mocked instance
    }
    @Test
    private void testFoo() {
        Foo foo = new Foo(); // Foo.bar should reference a mocked instance of Bar()
    }
}

您可以在Mockito中模拟新实例来完成复杂的事情,但是简单地注入测试所需的依赖项要简单得多

public class Foo {

    private Bar bar;

    Foo(Bar bar) {
        this.bar = bar;
    }
}

此时,您可以将想要的
Bar
的任何实例注入此类,包括mock。

您可以在Mockito中模拟新实例来完成复杂的事情,但是简单地注入测试中所需的依赖项要简单得多

public class Foo {

    private Bar bar;

    Foo(Bar bar) {
        this.bar = bar;
    }
}

此时,您可以将所需的
Bar
的任何实例注入此类,包括mock。

尝试PowerMockito和whenNew方法。当调用Foo类的构造函数时,您应该能够返回一个模拟实例。

尝试PowerMockito和whenNew方法。当调用Foo类的构造函数时,您应该能够返回一个模拟实例。

您可以使用一个支持模拟“新建”(未来)对象的模拟库来执行此操作。JMockit和PowerMock都支持它。例如,使用JMockit时,测试如下所示:

public class FooTest {
    @Test
    public void mockAllInstancesOfAClass(@Mocked Bar anyBar) {
        new Expectations() {{ anyBar.giveMe5(); result = 123; }};

        Foo foo = new Foo();
        // call method in foo which uses Bar objects

        // asserts and/or verifications
    }
}

您可以使用模拟库来实现这一点,该库支持模拟“新的”(未来)对象。JMockit和PowerMock都支持它。例如,使用JMockit时,测试如下所示:

public class FooTest {
    @Test
    public void mockAllInstancesOfAClass(@Mocked Bar anyBar) {
        new Expectations() {{ anyBar.giveMe5(); result = 123; }};

        Foo foo = new Foo();
        // call method in foo which uses Bar objects

        // asserts and/or verifications
    }
}

这类事情通常是通过依赖注入来完成的。那么
setBar(Bar)
方法呢。这将是最简单的解决方案,但您也可以通过反射进行设置。这类事情通常通过依赖项注入来完成。那么
setBar(Bar)
方法呢。这将是最简单的解决方案,但您也可以通过反射进行设置。实际上,我必须传播这种依赖注入并更改我的生产代码,以便运行测试。PowerMockito whenNew基本上就是我想要做的。如果
Bar
是一个真实的对象,也就是说,如果它在构造函数中初始化了实例状态(
newbar(1,“data”)
,那么这种方法就不起作用了。这样的对象不能通过DI注入。@Rogério:关键是在注入
Bar
时,要完全远离这种模式。上面的代码过于简单了。实际上,我必须传播这种依赖注入并更改我的生产代码,以便运行测试。PowerMockito whenNew基本上就是我想要做的。如果
Bar
是一个真实的对象,也就是说,如果它在构造函数中初始化了实例状态(
newbar(1,“data”)
,那么这种方法就不起作用了。这样的对象不能通过DI注入。@Rogério:关键是在注入
Bar
时要完全远离这种模式。