英文:
How to mock a sftp session
问题
我正在更新几个测试。在"Before"部分获取SFTP会话。为此,用户名和密码已在属性文件中硬编码。出于安全原因,密码不能被提交,必须被清空。然而单元测试在以下位置失败:
private DefaultSftpSessionFactory sftpClientFactory;
private SftpSession sftpSession;
@Before
public void setup() {
sftpSession = sftpClientFactory.getSession();
}
在这一步中,出现"either a password or private key is required"的错误。我想获得一个模拟会话,这样我就不必提供密码。
英文:
I am updating a few tests. The Before gets the sftp session. For this, the username and password have been hardcoded in the properties file. Due to security reasons, the password cannot be checked in and has to be blanked out. However the unit test fails at
private DefaultSftpSessionFactory sftpClientFactory;
private SftpSession sftpSession;
@Before
public void setup() {
sftpSession = sftpClientFactory.getSession();
}
This step fails with "either a password or private key is required".I would like to get a mock session, so that I dont have to provide a password.
答案1
得分: 2
如果您正在使用JUnit 5 Jupiter(可能也可以轻松适应JUnit 4),我已经编写了一篇关于如何使用atmoz/sftp Docker镜像与Testcontainers的文章。
完整的工作示例可以在这里找到:
https://overflowed.dev/blog/sftp-testing-junit-testcontainers-atmoz-sftp/
以下是您如何定义带有SFTP的TestContainer的基本示例:
private static final GenericContainer sftp = new GenericContainer(
new ImageFromDockerfile()
.withDockerfileFromBuilder(builder ->
builder
.from("atmoz/sftp:latest")
.run("mkdir -p /home/" + USER + "/upload; chmod -R 007 /home/" + USER)
.build()))
//.withFileSystemBind(sftpHomeDirectory.getAbsolutePath(), "/home/" + USER + REMOTE_PATH, BindMode.READ_WRITE) //取消注释以挂载主机目录 - 不是必需/推荐的
.withExposedPorts(PORT)
.withCommand(USER + ":" + PASSWORD + ":1001:::upload");
英文:
In case you are using JUnit 5 Jupiter (might be easily adaptable to JUnit 4 as well) I´ve written an article on how to do it using the atmoz/sftp Docker image together with Testcontainers.
The full working example can be found here
https://overflowed.dev/blog/sftp-testing-junit-testcontainers-atmoz-sftp/
This is basically how you would define your TestContainer with SFTP
private static final GenericContainer sftp = new GenericContainer(
new ImageFromDockerfile()
.withDockerfileFromBuilder(builder ->
builder
.from("atmoz/sftp:latest")
.run("mkdir -p /home/" + USER + "/upload; chmod -R 007 /home/" + USER)
.build()))
//.withFileSystemBind(sftpHomeDirectory.getAbsolutePath(), "/home/" + USER + REMOTE_PATH, BindMode.READ_WRITE) //uncomment to mount host directory - not required / recommended
.withExposedPorts(PORT)
.withCommand(USER + ":" + PASSWORD + ":1001:::upload");
答案2
得分: 1
关于未回答/可回答的问题 https://stackoverflow.com/q/22697/592355,一种 Mockito 的方法是:
-
将所需的库添加到您的(测试)类路径中。 (https://mvnrepository.com/artifact/org.mockito)
-
模拟 SftpSession。 (通过注释
private @Mock SftpSession sftpSession;
...加上相应的 初始化/启用,或者(手动)通过sftpSession = Mockito.mock(SftpSession.class);
)a. 查看是否需要(对于测试)SessionFactory,如果需要,也进行模拟。
-
模拟/验证/重置与模拟对象的任何交互(在您的测试中)。 (例如
Mockito.when(sftpSession.foo(x,y,z)).then...
或Mockito.verify(sftpSession, Mockito.times(n)).foo(x,y,z);
)
进一步阅读:
英文:
Regarding the unanswered/able question https://stackoverflow.com/q/22697/592355, a Mockito approach would be:
-
Get the needed libraries into your (test) class path. (https://mvnrepository.com/artifact/org.mockito)
-
Mock the SftpSession. (Via annotation
private @Mock SftpSession sftpSession;
...plus the according initialization/enablement, or (manually) viasftpSession = Mockito.mock(SftpSession.class);
)a. See, whether the SessionFactory is needed (for test) at all, if so also mock.
-
Mock/verify/reset any interactions (within your tests) with the mocked objects. (Like
Mockito.when(sftpSession.foo(x,y,z)).then...
orMockito.verify(sftpSession, Mockito.times(n)).foo(x,y,z);
)
Further reading:
答案3
得分: 0
我不知道所提及测试的目的,但作为对模拟的替代方案,我可以建议针对一个完全功能的SFTP服务器进行测试,就像最初的意图一样。
诀窍是使用Docker和一些Docker启用的Java库,比如Testcontainers。
- 选择一个SFTP服务器的Docker镜像(atmoz/sftp 可能值得一试 - 根据星级和下载次数来判断)- 确保它易于配置(在
atmoz/sftp
中,用户可以使用环境变量进行配置 - 参见文档)。 - 使用Testcontainers在你的测试中设置服务器(可以使用GenericContainer#addEnv为容器设置环境变量)。有关详细信息,请参阅Junit 4和Junit Jupiter的快速入门手册。
英文:
I don't know the purpose of the test in question, but as an alternative to mocking I could suggest testing against a fully functional SFTP server, just as originally intended.
The trick is to use Docker and some Docker-enablement java library like Testcontainers.
- Choose a SFTP server Docker image (atmoz/sftp might be worth a try - judging from the number of stars and downloads) - make sure it's easily configurable (in
atmoz/sftp
the users can be configured using environment vars - see the documentation). - Use Testcontainers to set up the server in your test (environment variables can for a container can be set using GenericContainer#addEnv). Consult the quick start manuals for Junit 4 and Junit Jupiter for details.
答案4
得分: 0
如 jannis 在这里所述,一个更好的选择是使用完全功能的测试SFTP环境。
为什么? 因为模拟逻辑需要大量样板代码,无法充分测试应用程序及其各个组成部分。幸运的是,测试容器的支持已经足够成熟,可以用于您的情况。
在 SpringBoot 环境中,SFTP 测试容器可以轻松设置如下:
@SpringBootTest
class SshClientDemoApplicationTests {
@Container
static final GenericContainer<?> SFTP = new GenericContainer<>("atmoz/sftp:latest")
.withExposedPorts(22)
.withCreateContainerCmdModifier(cmd -> cmd.withHostConfig(
new HostConfig().withPortBindings(new PortBinding(Ports.Binding.bindPort(22), new ExposedPort(22)))
))
.withCommand("user:pass:::home");
@BeforeAll
static void start() throws IOException {
SFTP.start();
}
@AfterAll
static void stop() {
SFTP.stop();
}
}
完整的可工作 Spring Boot 应用程序可在此处下载。
英文:
As mentioned by jannis here a better alternative is to use a fully functional test SFTP environment.
Why? Because mocking the logic requires a lot of boilerplate and does not allow one to fully test the application and its moving parts. Luckily, the test containers support is mature enough and can be used for your case.
The SFTP test container in a SpringBoot environment can be easily set up as follows:
@SpringBootTest
class SshClientDemoApplicationTests {
@Container
static final GenericContainer<?> SFTP = new GenericContainer<>("atmoz/sftp:latest")
.withExposedPorts(22)
.withCreateContainerCmdModifier(cmd -> cmd.withHostConfig(
new HostConfig().withPortBindings(new PortBinding(Ports.Binding.bindPort(22), new ExposedPort(22)))
))
.withCommand("user:pass:::home");
@BeforeAll
static void start() throws IOException {
SFTP.start();
}
@AfterAll
static void stop() {
SFTP.stop();
}
}
The full working Spring Boot application can be downloaded here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论