简体   繁体   English

如何使用 Spring MVC 控制器作为集成测试的假端点?

[英]How do I use a Spring MVC Controller as a Fake Endpoint for an Integration Test?

I have a service that calls out to a third-party endpoint using java.net.URLConnection .我有一个使用java.net.URLConnection调用第三方端点的服务。 As part of an integration test that uses this service I would like to use a fake endpoint of my own construction.作为使用此服务的集成测试的一部分,我想使用我自己构建的假端点。

I have made a Spring MVC Controller that simulates that behaviour of the endpoint I require.我制作了一个 Spring MVC 控制器来模拟我需要的端点的行为。 (I know this endpoint works as expected as I included it in my web app's servlet config and hit it from a browser once started). (我知道这个端点按预期工作,因为我将它包含在我的 Web 应用程序的 servlet 配置中,并在启动后从浏览器点击它)。

I am having trouble figuring out how I can get this fake endpoint available for my integration test.我无法弄清楚如何让这个假端点可用于我的集成测试。

Is there some feature of Spring-Test that would help me here? Spring-Test 是否有一些功能可以帮助我? Do I somehow need to start up a servlet at the beginning of my test?我是否需要在测试开始时启动一个 servlet? Are there any other solutions entirely?完全有其他解决方案吗?

It's a bad idea to use a Spring MVC controller as a fake endpoint.将 Spring MVC 控制器用作假端点是一个坏主意。 There is no way to simply have the controller available for the integration test and starting a servlet with just that controller alongside whatever you are testing requires a lot of configuration.没有办法简单地让控制器可用于集成测试,并且仅使用该控制器启动 servlet 以及您正在测试的任何东西都需要大量配置。

It is much better to use a mocking framework like MockServer ( http://www.mock-server.com/ ) to create your fake endpoint.使用像 MockServer ( http://www.mock-server.com/ ) 这样的模拟框架来创建你的假端点要好得多。 MockServer should be powerful enough to cover even complex responses from the fake endpoint, with relatively little setup. MockServer 应该足够强大,可以覆盖来自假端点的复杂响应,而设置相对较少。

Check out Spring MVC Test that was added to Spring in version 3.2.查看在 3.2 版中添加到 Spring 的 Spring MVC 测试。

Here are some tutorials: 1 , 2 , 3这里有一些教程: 1 , 2 , 3

First I think we should get the terminology right.首先,我认为我们应该正确使用术语。 There are two general groups of "fake" objects in testing (simplified): a mock, which returns predefined answers on predefined input and stubs which are a simplified version of the object the SUT (system under test) communicates with.在测试(简化)中有两组通用的“假”对象:一个模拟,它在预定义的输入和存根上返回预定义的答案,存根是 SUT(被测系统)与之通信的对象的简化版本。 While a mock basically does nothing than to provide a response, a stub might use a live algorithm, but not store it's results in a database or send them to customers via eMail for example.虽然模拟基本上只是提供响应,但存根可能会使用实时算法,但不会将其结果存储在数据库中或通过电子邮件发送给客户。 I am no expert in testing, but those two fake objects are rather to be used in unit and depending on their scope in acceptance tests.我不是测试专家,但这两个假对象更适合在单元中使用,并取决于它们在验收测试中的范围。

So your sut communicates with a remote system during integration test .因此,您的 sut 在集成测试期间与远程系统通信。 In my book this is the perfect time to actually test how your software integrates with other systems, so your software should be tested against a test version of the remote system.在我的书中,这是实际测试您的软件如何与其他系统集成的最佳时机,因此您的软件应该针对远程系统的测试版本进行测试。 In case this is not possible (they might not have a test system) you are conceptually in some sort of trouble.如果这是不可能的(他们可能没有测试系统),您在概念上会遇到某种麻烦。 You can shape your stub or mock only in a way you expect it to work, very much like the part of the software you have written to communicate with that remote service.您只能以您希望它工作的方式塑造您的存根或模拟,这非常类似于您编写的用于与该远程服务通信的软件部分。 This leaves out some important things you want to test with integration tests: Was the client side implemented correctly so that it will work with the live server.这遗漏了一些您想要使用集成测试进行测试的重要事项: 客户端是否正确实现,以便它可以与实时服务器一起使用。 Do we have to develop work around as there are implementation errors on the server side?由于服务器端存在实现错误,我们是否必须制定解决方案? In which scale will the communication with the remote system affect our software's performance?与远程系统的通信会在多大程度上影响我们的软件性能? Do our authentication credentials work?我们的身份验证凭据有效吗? Does the authentication mechanism work?身份验证机制是否有效? What are the technical and conceptual implications of this communication relationship no one has thought of so far?迄今为止没有人想到这种沟通关系的技术和概念含义是什么? (Believe me, the latter will happen more often than you might expect!) (相信我,后者会比你想象的更频繁!)

Generally speaking: What will happen if you do integration tests against a mock or a stub is that you test against your own understanding of how to implement the client and the server side of communication, and you do not test how your client works with the actual remote server or at least the best thing next to that, a test system.一般而言:如果您针对模拟或存根进行集成测试会发生什么情况是您根据自己对如何实现客户端和服务器端通信的理解进行测试,而不是测试您的客户端如何与实际工作远程服务器或至少旁边最好的东西,一个测试系统。 I can tell you from experience: never make assumptions on how a remote system should behave - test it.我可以从经验告诉你:永远不要对远程系统的行为做出假设——测试它。 Even when talking of a JMS server: test it!即使在谈论 JMS 服务器时:测试它!

In case you are working for a company, testing against a provided test system is even more important: if you software works against a test system and you can prove it (selenium is a good helper here, as well as good logging, believe it or not) and your software does not work with a live version, you have a situation which I call "instablame": it is immediately obvious that it is not your fault the software isn't working.如果您为公司工作,则针对提供的测试系统进行测试更为重要:如果您的软件针对测试系统工作并且您可以证明它(selenium 是这里的好帮手,以及良好的日志记录,请相信它或不),并且您的软件无法与实时版本一起使用,您会遇到一种我称之为“instablame”的情况:很明显,软件无法运行不是您的错。 I myself hate fingerpointing to the bone, but most suits tend to ask "Who's fault was it?"我自己讨厌用手指指着骨头,但大多数西装往往会问“是谁的错?” even before "Can we fix that immediately?"甚至在“我们可以立即解决这个问题吗?” and way before "How can we solve that problem?".以及“我们如何解决这个问题?”之前的方式。 And there is a special group of suits called lawyers, you know ... ;)还有一个特殊的诉讼组叫做律师,你知道......;)

That being said: if you absolutely have to use those stubs during your integration tests, I would create an own project for them (let's say " MyProject-IT-Stubs " and build and run the latest version of MyProject-IT-Stubs before I run the IT of my main project. When using maven, you could create MyProject-IT-Stubs with war packaging, call it as a dependency during the pre-integration-test phase and fire up a jetty for this war in the same phase. Then your integration tests run, either successful or not and you can tear down the jetty in the post-integration-test phase.话虽如此:如果您在集成测试期间绝对必须使用这些存根,我会为它们创建一个自己的项目(假设“ MyProject-IT-Stubs ”并在我之前构建和运行最新版本的MyProject-IT-Stubs运行我的主项目的 IT。在使用 maven 时,您可以创建带有war包装的MyProject-IT-Stubs ,在预集成-测试阶段将其称为依赖项,并在同一阶段为此战争启动码头。然后您的集成测试运行,无论成功与否,您可以在后集成测试阶段拆除码头。

The IMHO best way to organize your project with maven would be to have a project with three modules: MyProject , MyProject-IT-Stubs and MyProject-IT (declaring dependencies on MyProject and MyProject-IT-Stubs . This keeps your projects nice and tidy and the stubs do not pollute your project. You might want to think about organizing MyProject-IT-Stubs into modules as well, one for each remote system you have to talk to. As soon as you have test access, you can simply deactivate the according module in MyProject-IT-Stubs .恕我直言,使用 maven 组织您的项目的最佳方法是拥有一个包含三个模块的项目: MyProjectMyProject-IT-StubsMyProject-IT (声明对MyProjectMyProject-IT-Stubs依赖。这使您的项目保持整洁并且存根不会污染您的项目。您可能还想考虑将MyProject-IT-Stubs组织成模块,每个模块对应一个您必须MyProject-IT-Stubs远程系统。一旦您拥有测试访问权限,您就可以简单地停用根据MyProject-IT-Stubs模块。

I am sure according options exist for InsertYourBuildToolHere .我确信InsertYourBuildToolHere存在相应的选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM