我是Mockito的新手。
给定下面的类,我如何使用Mockito来验证someemethod在foo被调用后恰好被调用一次?
public class Foo
{
public void foo(){
Bar bar = new Bar();
bar.someMethod();
}
}
我想打电话确认一下,
verify(bar, times(1)).someMethod();
其中bar是bar的模拟实例。
我是Mockito的新手。
给定下面的类,我如何使用Mockito来验证someemethod在foo被调用后恰好被调用一次?
public class Foo
{
public void foo(){
Bar bar = new Bar();
bar.someMethod();
}
}
我想打电话确认一下,
verify(bar, times(1)).someMethod();
其中bar是bar的模拟实例。
当前回答
我认为Mockito @InjectMocks是正确的选择。
根据你的意图,你可以使用:
构造函数注入 属性setter注入 字段注入
文档中的更多信息
下面是一个字段注入的例子:
类:
public class Foo
{
private Bar bar = new Bar();
public void foo()
{
bar.someMethod();
}
}
public class Bar
{
public void someMethod()
{
//something
}
}
测试:
@RunWith(MockitoJUnitRunner.class)
public class FooTest
{
@Mock
Bar bar;
@InjectMocks
Foo foo;
@Test
public void FooTest()
{
doNothing().when( bar ).someMethod();
foo.foo();
verify(bar, times(1)).someMethod();
}
}
其他回答
另一种简单的方法是向bar.someMethod()中添加一些日志语句,然后确定在测试执行时可以看到所述消息,参见示例:如何对日志记录器中的消息执行JUnit断言
当你的Bar.someMethod()是私有的时候,这是特别方便的。
是的,如果你真的想要/需要这样做,你可以使用PowerMock。这应该被视为最后的手段。使用PowerMock,可以使它从对构造函数的调用中返回一个模拟。然后在模拟上进行验证。也就是说,csturtz的答案是“正确的”。
这里是新对象的模拟构造的链接
依赖注入
如果您注入Bar实例,或用于创建Bar实例的工厂(或其他483种方法中的一种),您将拥有执行测试所需的访问权限。
工厂的例子:
给定一个这样的Foo类:
public class Foo {
private BarFactory barFactory;
public Foo(BarFactory factory) {
this.barFactory = factory;
}
public void foo() {
Bar bar = this.barFactory.createBar();
bar.someMethod();
}
}
在你的测试方法中,你可以像这样注入一个BarFactory:
@Test
public void testDoFoo() {
Bar bar = mock(Bar.class);
BarFactory myFactory = new BarFactory() {
public Bar createBar() { return bar;}
};
Foo foo = new Foo(myFactory);
foo.foo();
verify(bar, times(1)).someMethod();
}
奖励:这是TDD(测试驱动开发)如何驱动代码设计的一个例子。
如果您不想使用DI或工厂。你可以用一种小技巧重构你的类:
public class Foo {
private Bar bar;
public void foo(Bar bar){
this.bar = (bar != null) ? bar : new Bar();
bar.someMethod();
this.bar = null; // for simulating local scope
}
}
和你的测试类:
@RunWith(MockitoJUnitRunner.class)
public class FooTest {
@Mock Bar barMock;
Foo foo;
@Test
public void testFoo() {
foo = new Foo();
foo.foo(barMock);
verify(barMock, times(1)).someMethod();
}
}
然后调用foo方法的类会这样做:
public class thirdClass {
public void someOtherMethod() {
Foo myFoo = new Foo();
myFoo.foo(null);
}
}
正如你所看到的,当以这种方式调用方法时,你不需要在任何其他调用foo方法的类中导入Bar类,这可能是你想要的。
当然,缺点是您允许调用者设置Bar对象。
希望能有所帮助。
我认为Mockito @InjectMocks是正确的选择。
根据你的意图,你可以使用:
构造函数注入 属性setter注入 字段注入
文档中的更多信息
下面是一个字段注入的例子:
类:
public class Foo
{
private Bar bar = new Bar();
public void foo()
{
bar.someMethod();
}
}
public class Bar
{
public void someMethod()
{
//something
}
}
测试:
@RunWith(MockitoJUnitRunner.class)
public class FooTest
{
@Mock
Bar bar;
@InjectMocks
Foo foo;
@Test
public void FooTest()
{
doNothing().when( bar ).someMethod();
foo.foo();
verify(bar, times(1)).someMethod();
}
}