莫基托间谍不适用于工厂豆方法



我有一个弹簧靴,我正在为它编写单元测试。有一个工厂Bean,我在运行时从中获取服务对象。我想测试是否调用了此服务对象上的特定方法。这是应用代码

@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 被模拟,但 secretService 在 AppClient 中为空。 也就是说,secretService 没有被存根。 通过调试器进行测试。

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(..)
}

最新更新