Java 如何模拟事件处理程序?
我为Stash编写了一个事件处理程序,通过消息总线体系结构发送消息。下面是我的Java 如何模拟事件处理程序?,java,events,junit,mockito,Java,Events,Junit,Mockito,我为Stash编写了一个事件处理程序,通过消息总线体系结构发送消息。下面是我的fedmsgEventListener类中的一个示例: @EventListener public void opened(PullRequestOpenedEvent event) { HashMap<String, Object> message = prExtracter(event); String originProjectKey = ((HashMap<String, Ob
fedmsgEventListener
类中的一个示例:
@EventListener
public void opened(PullRequestOpenedEvent event)
{
HashMap<String, Object> message = prExtracter(event);
String originProjectKey = ((HashMap<String, Object>)message.get("source")).get("project_key").toString();
String originRepo = ((HashMap<String, Object>)message.get("source")).get("repository").toString();
String topic = originProjectKey + "." + originRepo + ".pullrequest.opened";
sendMessage(topic, message);
}
下面是测试调用的类和方法:
import com.atlassian.sal.api.ApplicationProperties;
import com.atlassian.stash.event.pull.*;
import org.mockito.Mock;
import static org.mockito.Mockito.*;
public class MyPluginComponentImpl implements MyPluginComponent
{
@Mock private PullRequestEvent event;
@Mock private PullRequestOpenedEvent opened;
@Mock private FedmsgEventListener fedmsgEventListener;
public MyPluginComponentImpl(ApplicationProperties applicationProperties)
{
this.applicationProperties = applicationProperties;
}
public String openPullRequest()
{
fedmsgEventListener.opened(opened);
return fedmsgEventListener.getTopic();
}
}
现在,该方法抛出一个NullPointerException
,因为fedmsgEventListener
和PullRequestEvent
都是模拟对象,因此为null
这是对这个场景进行单元测试的最佳方式吗?从较高的层次来看,这就是我想要做的:触发事件,查看主题是否已更改为包含特定字符串的字符串 您使用Mockito是完全错误的。很抱歉首先,
@Mock
如果不使用initMocks
或MockitoJUnitRunner
,就无法工作,但无论如何我不会这样做。模拟为非空;您应该能够在mock上调用方法;在您的例子中,您没有初始化/创建模拟,这就是为什么它们为空
首先,确定要测试的类。这里好像是FedmsgEventListener。然后,使用模拟对象和数据结构与该类的real实例交互,而不是使用具有依赖关系的真实对象等等。注意,我在这里使用
基于模拟的测试建立在:
Mockito.Verify
和JUnit/Hamcrestassert
方法来确保事情按预期的方式进行import static org.mockito.Mockito.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
private HashMap<String, Object> createMessageDetails(String project_key, String repository) {
HashMap<String, Object> details = new HashMap<>();
details.put("project_key", project_key);
details.put("repository", repository);
return details;
}
public class FedmsgEventListenerTest {
@Test
public void testOpened() {
// when
PullRequestOpenedEvent event = mock(PullRequestOpenedEvent.class);
when(event.someMethodForPrExtracterYouHaventShownMe()).thenReturn(createMessageDetails("myKey", "myRepo"));
// then
FedmsgEventListener listener = new FedmsgEventListener();
listener.opened(event);
// verify
assertThat(event.getTopic(), containsString(".pullrequest.opened"));
verify(event).someMethodForPrExtracterYouHaventShownMe();
}
}
import static org.mockito.mockito.*;
导入静态org.hamcrest.matcherasert.assertThat;
导入静态org.hamcrest.Matchers.containssString;
私有HashMap createMessageDetails(字符串项目密钥,字符串存储库){
HashMap details=新的HashMap();
详细信息。放置(“项目密钥”,项目密钥);
详细信息。放置(“存储库”,存储库);
退货详情;
}
公共类FedmsgEventListenerTest{
@试验
公开作废testOpened(){
//什么时候
PullRequestOpenedEvent=mock(PullRequestOpenedEvent.class);
when(event.somemethodforprextracteryyouhaveshownme())。然后返回(createMessageDetails(“myKey”、“myRepo”);
//然后
FedmsgEventListener listener=新的FedmsgEventListener();
listener.opened(事件);
//核实
断言(event.getTopic(),包含字符串(“.pullrequest.opened”);
验证(event).someMethodforPrextracteryYouhaventShowNME();
}
}
这段代码可能并不完全是您所需要的,但是您还没有向我展示足够的代码,您正试图为我测试这些代码以使其完全正确。然而,我认为这应该足以让你开始
另一方面,如果您不能创建具有模拟依赖项的类的真实实例,那么这就是一种代码味道,您的代码应该重构。这就是为什么静态是个坏主意的原因之一,因为如果代码通过静态访问全局状态,那么必须使用静态设置全局状态。使您的类能够处理模拟依赖项,将它们作为参数传递给构造函数,在时使用
指定模拟行为,然后断言/验证结果。@durron597好的,尝试以更好的方式描述它。告诉我是否更好。谢谢你的详尽回答。我的类FedmsgEventListener
似乎在它所监视的事件发生时被实例化。此时,许多与事件相关的参数被提供给类的构造函数。我可能可以模拟这些参数,但我不确定会有什么副作用。不管是哪种方式,谢谢你提供了使用mock的基本说明。@ScottJamesWalter很高兴我能帮上忙。如果发生这种情况,那么听起来您的代码耦合得太紧密,可能会经受住重构。看见
import static org.mockito.Mockito.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
private HashMap<String, Object> createMessageDetails(String project_key, String repository) {
HashMap<String, Object> details = new HashMap<>();
details.put("project_key", project_key);
details.put("repository", repository);
return details;
}
public class FedmsgEventListenerTest {
@Test
public void testOpened() {
// when
PullRequestOpenedEvent event = mock(PullRequestOpenedEvent.class);
when(event.someMethodForPrExtracterYouHaventShownMe()).thenReturn(createMessageDetails("myKey", "myRepo"));
// then
FedmsgEventListener listener = new FedmsgEventListener();
listener.opened(event);
// verify
assertThat(event.getTopic(), containsString(".pullrequest.opened"));
verify(event).someMethodForPrExtracterYouHaventShownMe();
}
}