我在编写可工作的骆驼弹簧启动单元测试时遇到了一些麻烦,该测试可以测试简单的SNMP路由。这是我到目前为止的内容:
SnmpRoute.kt
open class SnmpRoute(private val snmpProperties: SnmpProperties, private val repository: IPduEventRepository) : RouteBuilder() {
@Throws(Exception::class)
override fun configure() {
logger.debug("Initialising with properties [{}]", snmpProperties)
from("snmp:0.0.0.0:1161?protocol=udp&type=TRAP")
.process { exchange ->
// do stuff
}
.bean(repository, "save")
}
}
SnmpRouteTest.kt
@CamelSpringBootTest
@SpringBootApplication
@EnableAutoConfiguration
open class SnmpRouteTest : CamelTestSupport() {
object SnmpConstants {
const val SNMP_TRAP = "<snmp><entry><oid>...datadatadata...</oid><value>123456</value></entry></snmp>"
const val MOCK_SNMP_ENDPOINT = "mock:snmp"
}
@Mock
lateinit var snmpProperties: SnmpProperties
@Mock
lateinit var repository: IPduEventRepository
@InjectMocks
lateinit var snmpRoute: SnmpRoute
@EndpointInject(SnmpConstants.MOCK_SNMP_ENDPOINT)
lateinit var mock: MockEndpoint
@Before
fun setup() {
initMocks(this)
}
@Throws(Exception::class)
override fun createRouteBuilder(): RouteBuilder {
return snmpRoute
}
@Test
@Throws(Exception::class)
fun `Test SNMP endpoint`() {
mock.expectedBodiesReceived(SnmpConstants.SNMP_TRAP)
template.sendBody(SnmpConstants.MOCK_SNMP_ENDPOINT,
SnmpConstants.SNMP_TRAP)
mock.assertIsSatisfied()
verify(repository).save(PduEvent(1234, PDU.TRAP))
}
}
但是,当我运行此测试时,它失败了,因为repository
模拟从未有任何交互:
Wanted but not invoked:
repository.save(
PduEvent(requestId=1234, type=-89)
);
-> at org.meanwhile.in.hell.camel.snmp.route.SnmpRouteTest.Test SNMP endpoint(SnmpRouteTest.kt:61)
Actually, there were zero interactions with this mock.
[有人可以帮我理解为什么无法正确交互吗?手动运行时,它可以正常工作并按预期保存。
现在我明白了这里发生了什么!您的被测RouteBuilder
有一个from("snmp")
。如果希望在此处传递模拟消息以进行测试,则需要在测试执行期间将snmp:
组件交换为direct:
或direct:
组件。
您当前的测试正在将消息传递到Mock端点,并验证是否在此处收到了该消息。它不与实际路线构建器交互。这就是您的模拟终结点声明确实通过但seda:
失败的原因。
TL; DR
假设您使用的是Apache Camel 3.x,请按照以下步骤操作。我不太会Kotlin,因此,我将向您展示如何用Java做到这一点。
seda:
Mockito.verify()
)AdviceWithRouteBuilder.adviceWith(context, "route-id", routeBuilder -> {
routeBuilder.replaceFromWith("direct:snmp-from"); //Replaces the from part of the route `route-id` with a direct component
});
组件而不是SNMPTL; DR结束。
下面的完整示例代码。
PojoRepo.java
route-id
SNMPDummyRoute.java
direct:
SNMPDummyRoteTest.java
注意:此类使用@Component
public class PojoRepo {
public void save(String body){
System.out.println(body);
}
}
而不是扩展@Component
public class SNMPDummyRoute extends RouteBuilder {
PojoRepo pojoRepo;
public SNMPDummyRoute(PojoRepo pojoRepo) {
this.pojoRepo = pojoRepo;
}
@Override
public void configure() throws Exception {
from("snmp:0.0.0.0:1161?protocol=udp&type=TRAP")
.id("snmp-route")
.process(exchange -> {
exchange.getMessage().setBody(String.format("Saw message [%s]", exchange.getIn().getBody()));
})
.to("log:snmp-log")
.bean(pojoRepo, "save");
}
}
,但核心思想是相同的。
CamelSpringBootRunner
下面来自测试运行的日志。仔细查看SNMP端点与直接组件交换的XML片段。
CamelTestSupport