【问题标题】:Mock local variable in Junit, Mockito在 Junit,Mockito 中模拟局部变量
【发布时间】:2021-11-19 23:18:32
【问题描述】:

我正在为使用 Mockito 的代码编写测试用例。代码是这样的,

public class Example {
 
 @Autowired
 private HelperService hs; 

 public void someMethod() {
   List<String> names = new ArrayList<>();
   hs.addValues(names);
   if(names.size() < 5) {throw new RuntimeException("Invalid names list");}
   return;
 }

}

public class HelperService {

 public void addValues(List<String> names) {
  names.add("alex");
  names.add("harry");
  names.add("james");
  names.add("maria");
  names.add("bob");
 }

}

我知道这是一个人为的例子,但我有一个类似的用例,我无法修改现有代码。我想使用 JunitMockitoExample 类进行单元测试。如何测试names.size() 的异常情况

【问题讨论】:

  • 在您的测试中注入一个模拟 HelperService(它会添加更少的名称)。
  • 或者甚至只是扩展 HelperService 并覆盖该方法,然后注入您的扩展。甚至不需要在这里嘲笑。
  • 扩展是什么意思?你能详细说明一下吗?我打算使用 Junit 和 Mockito 编写一个 UNIT 测试来模拟外部依赖项。
  • 添加示例作为答案。
  • 另外,模拟外部依赖并不总是必要的。当类足够简单时,有时只需提供不同的(通过下面显示的普通extends 选项)就足够了。

标签: java spring spring-boot junit mockito


【解决方案1】:

我假设您已经有一种方法可以在您的测试中设置HelperService 字段(无论是通过将其设置为@SpringBootTest、使用@InjectMocks 还是其他方式)。所以这只会提供一个选项,让你可以做你想做的事:

  1. 扩展 HelperService 并注入:
// Inject this into your class under test
private HelperService hs = new LessThan5NameAddingHelperService();

class LessThan5NameAddingHelperService extends HelperService {
    @Override
    public void addNames( List<String> names ) {
        names.add( "Dave" );
    }
}
  1. 提供一个mock HelperService,它的作用相同:
// Inject this into your class under test
private HelperService hs;

@Before
public void setupMockHelperService() {
    hs = mock( HelperService.class );

    doAnswer( invocation -> {
        List<String> names = ( List<String> ) invocation.getArguments()[0];
        names.add( "Dave" );
        return null;
    } ).when( hs ).addNames( any() );
}

【讨论】:

  • 这两个选项看起来都不错。只是出于好奇,还有其他简短而优雅的方法可以达到同样的效果吗?
  • 很遗憾,如果您无法修改代码,则不会。如果您可以将 HelperService 设为 interface(并在生产环境中实现),那么您可以将其替换为 lambda:hs = names -&gt; { names.add("Dave"); };,甚至只是 hs = names -&gt; {};
  • 我明白了。无论如何,你的两个答案虽然有点冗长,但看​​起来很整洁。
  • 抱歉,我昨天本来打算发表评论的。模拟的默认行为是对 void 方法不做任何事情。因此,如果您不需要任何行为(即根本没有添加名称),那么您可以跳过第二个解决方案的整个 doAnswer 部分,只使用 hs = mock( HelperService.class );
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-07
  • 2016-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-31
  • 1970-01-01
相关资源
最近更新 更多