java如何在方法中使用对象_java - Mockito:如何在方法中创建的对象上调用方法?...

java - Mockito:如何在方法中创建的对象上调用方法?

我是Mockito的新手。

鉴于下面的课程,如何在调用Bar之后使用Mockito来验证bar是否被调用了一次?

public class Foo

{

public void foo(){

Bar bar = new Bar();

bar.someMethod();

}

}

我想进行以下验证通话,

verify(bar, times(1)).someMethod();

其中bar是Bar的模拟实例。

7个解决方案

259 votes

依赖注入

如果您注入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如何推动代码设计的一个例子。

csturtz answered 2019-03-05T09:44:39Z

18 votes

经典的回答是,“你没有。” 您测试Foo的公共API,而不是其内部。

是否存在受foo()影响的Foo对象(或不太好,环境中的其他对象)的任何行为? 如果是这样,请测试一下。 如果没有,该方法有何作用?

Michael Brewer-Davis answered 2019-03-05T09:45:13Z

10 votes

如果您不想使用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 Object。

希望能帮助到你。

raspacorp answered 2019-03-05T09:46:08Z

7 votes

我认为Mockito @InjectMocks是要走的路。

根据您的意图,您可以使用:

构造函数注入

物业二传手注射

现场注射

更多信息在docs中

以下是现场注入的示例:

类别:

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();

}

}

siulkilulki answered 2019-03-05T09:47:27Z

6 votes

使用PowerMockito.whenNew解决您的示例代码

mockito-all 1.10.8

powermock-core 1.6.1

powermock-module-junit4 1.6.1

powermock-api-mockito 1.6.1

junit 4.12

FooTest.java

package foo;

import org.junit.After;

import org.junit.Before;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.mockito.Mock;

import org.mockito.Mockito;

import org.powermock.api.mockito.PowerMockito;

import org.powermock.core.classloader.annotations.PrepareForTest;

import org.powermock.modules.junit4.PowerMockRunner;

//Both @PrepareForTest and @RunWith are needed for `whenNew` to work

@RunWith(PowerMockRunner.class)

@PrepareForTest({ Foo.class })

public class FooTest {

// Class Under Test

Foo cut;

@Mock

Bar barMock;

@Before

public void setUp() throws Exception {

cut = new Foo();

}

@After

public void tearDown() {

cut = null;

}

@Test

public void testFoo() throws Exception {

// Setup

PowerMockito.whenNew(Bar.class).withNoArguments()

.thenReturn(this.barMock);

// Test

cut.foo();

// Validations

Mockito.verify(this.barMock, Mockito.times(1)).someMethod();

}

}

JUnit输出

gHdue.png

javaPlease42 answered 2019-03-05T09:48:37Z

3 votes

是的,如果您真的想要/需要这样做,您可以使用PowerMock。 这应该被视为最后的手段。 使用PowerMock,您可以使它从调用返回模拟构造函数。 然后在模拟上进行验证。 也就是说,csturtz是“正确”的答案。

这是Mock构造新对象的链接

John B answered 2019-03-05T09:49:10Z

0 votes

另一个简单的方法是将一些日志语句添加到bar.someMethod(),然后确定您可以在执行测试时看到所述消息,请参阅此处的示例:如何在记录器中对消息执行JUnit断言

当你的Bar.someMethod()是private时,这是特别方便的。

Nestor Milyaev answered 2019-03-05T09:49:43Z

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值