gpt4 book ai didi

java - mockito 测试对抽象执行器的调用

转载 作者:行者123 更新时间:2023-12-02 11:20:45 25 4
gpt4 key购买 nike

我正在对遗留代码进行测试,在重构之前,这意味着我不应该更改该代码...我正在使用 Spring 和 Hazelcast,我的类是 Hazelcast Listener(如果您不了解 Hazelcast 也没关系,只需注意我无法更改该方法的公司)。

@Component
public class MyClass implements EntryAddedListener<String, MyEntry> {

@Autowired
@Qualifier( "asyncExecutor" )
private Executor executor;

@Autowired
private ClassToBeCalled classToBeCalled;

@Override
public void entryAdded( final EntryEvent<String, MyEntry> event ) {
executor.execute( () -> {
...
...
classToBeCalled.methodToBeCalled( event.getValue() );
}
} );
}
}

我想测试当entryAdded被调用时,execute被调用,特别是methodToBeCalled也被调用。我正在尝试不同的方法,但所有方法都遇到了一些模拟错误。这是最后一篇:

@RunWith(MockitoJUnitRunner.class)
public class MyClass {

@Mock
private Executor asyncExecutor;

@Mock
private ClassToBeCalled classToBeCalled;

@InjectMocks
private MyClass myClass;

@Test
public void entryListenerShouldInvokeTheClassToBeCalled(){
// given
EntryEvent entryEvent = mock(EntryEvent.class);
MyEntry value = mock(MyEntry.class);
when(entryEvent.getValue()).thenReturn(value);

// here some of my tries, all commented because they don't work
// doCallRealMethod().when(asyncExecutor).execute(any(Runnable.class));
// when(executor.execute(any(Runnable.class))).thenCallRealMethod();

// when
myClass.entryAdded(entryEvent);

// then
verify(asyncExecutor, times(1)).execute(any(Runnable.class));
verify(classToBeCalled, times(1)).methodToBeCalled(value);
}
}

基本上我无法验证是否调用了methodToBeCalled,因为Executor是一个抽象类。我无法监视它,我无法调用真正的方法。另外,@Qualifier 指的是库中的实现,它或多或少是:

    @Bean(name = {"AsyncExecutor"})
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
...
...
executor.initialize();
return executor;
}

有什么想法吗?

最佳答案

您尝试使用太多模拟。您正在 mock Executor,但仍然期望它表现得像常规的 Executor,这显然是行不通的。

而是使用SyncTaskExecutor,它基本上使对executor.execute的调用成为测试的同步调用,并且仅模拟ClassToBeCalled

像这样,使用 ReflectionTestUtils 应该可以解决问题。

public class MyClass {

private Executor executor = new SyncTaskExector();
private ClassToBeCalled classToBeCalled;

private MyClass myClass;

@Before
public setup() {
myClass = new MyClass();
classToBeCalled = mock(ClassToBeCalled.class);
RelfectionTestUtils.setField(myClass, "executor", executor);
RelfectionTestUtils.setField(myClass, "classToBeCalled", classToBeCalled);
}

@Test
public void entryListenerShouldInvokeTheClassToBeCalled(){
// given
EntryEvent entryEvent = mock(EntryEvent.class);
MyEntry value = mock(MyEntry.class);
when(entryEvent.getValue()).thenReturn(value);

// when
myClass.entryAdded(entryEvent);

// then
verify(classToBeCalled, times(1)).methodToBeCalled(value);
}
}

调用 methodToBeCalled 的事实也是 execute 方法被执行的证据。

提示:我建议将其更改为使用基于构造函数的注入(inject)而不是字段注入(inject),因为这使测试变得更加容易。

@Component
public class MyClass implements EntryAddedListener<String, MyEntry> {

private final Executor executor;
private final ClassToBeCalled classToBeCalled;

@Autowired
public MyClass(@Qualifier("asyncExecutor") Executor executor, ClassToBeCalled classToBeCalled) {
this.executor=executor;
this.classToBeCalled=classToBeCalled;
}
}

现在您可以删除 ReflectionTestUtils 并简单地构造您的对象。

@Before
public void setup() {
classToBeCalled = mock(ClassToBeCalled.class);
myClass = new MyClass(executor, classToBeCalled);
}

关于java - mockito 测试对抽象执行器的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49938917/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com