【问题标题】:mockito spy does not work on a factory bean methodmockito spy 不适用于工厂 bean 方法
【发布时间】:2019-06-13 05:33:47
【问题描述】:

我有一个正在为其编写单元测试的 springboot。有一个 factoryBean,我在运行时从中获取服务对象。我想测试是否调用了此服务对象上的特定方法。这是应用程序代码

@Component
public class AppClient {

    @Autowired
    ServiceFactory factory

    Service secretService

    @postContruct
    public void init(){
        this.secretService=factory.get("secret");
    }

    public void process(Map<String, Object> param){
        for (String key: param.keySet()){
            if (key.equals("foobar")){
                restService.handle(param.get(key));
            }
        }
    }
}

这是我的单元测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {

  @Autowired
  AppClient appClient;

  @SpyBean
  ServiceFactory factory;

  Service secretService;

  @Before
  public void init(){
    this.secretService=Mockito.spy(factory.get("secret"));
  }

  @Test
  public void testProcess() {
    Object obj = new MyDummyObject();
    Map<String, Object> params = new HashMap<>();
    params.put("foobar", obj);
    appClient.process(params);
    Mockito.verify(secretService).handle(obj);
  }
}

测试失败,当我通过调试器运行时,我看到调用了句柄。那么这里有什么问题呢?

编辑

@MockBean
ServiceFactory factory;

@Mock
Service secretService

@Before
public void init(){
  Mockito.when(factory.get(eq("secret"))).thenReturn(secretService);
}

通过此更改,工厂 bean 被模拟,但在 AppClient 中的 secretService 为空。也就是说,secretService 没有被存根。通过调试器进行测试。

【问题讨论】:

  • 我建议你调试你的测试,看看restService.handle是否真的被调用,以及参数是否真的是你的MyDummyObject。然后你就会知道是不是你对 Mockito 的使用实际上是错误的。
  • 没错,错过了。抱歉,我会删除我的评论以避免混淆。
  • @DawoodibnKareem 如果你看到帖子,我提到了我在调试器中观察到的内容
  • 但它是在您在测试中创建的同一个 MyDummyObject 上调用的吗?
  • @DawoodibnKareem 在同一个对象上调用(因为等于和哈希码被覆盖)

标签: java spring-boot mockito spring-boot-test springmockito


【解决方案1】:

PostConstruct 回调在 spring 应用程序完全运行之前执行,并且在您的测试类在工厂的模拟上做一些准备之前。您无法在 PostConstruct 回调中运行的代码上声明 Mockito when().then() 期望。

我可以建议你在 AppClient bean 中进行基于构造函数的注入:

@Component
public class AppClient {

    private final ServiceFactory factory

    @Autowired
    public AppClient(ServiceFactory factory){
       this.factory = factory;
    }

    ...
}

并将其作为简单的单元测试进行测试。通过手动创建 AppClient 的实例,注入工厂的模拟,执行 init 方法并验证您需要的所有内容:

@Test
void initTest(){
  when(factory.get(..)).thenReturn(..);

  AppClient client = new AppClient(factory);
  client.init();

  verify(..)
}

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 2021-09-02
    • 1970-01-01
    • 2012-08-29
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    相关资源
    最近更新 更多