【问题标题】:How to mock a file required by a Bean at initialization in JUnit tests如何在 JUnit 测试中模拟 Bean 在初始化时所需的文件
【发布时间】:2016-07-25 16:52:40
【问题描述】:

我有一个在初始化时读取文件的 Bean。该文件是特定于环境的,是在系统安装期间生成的。文件的路径被硬编码为代码中的最终静态变量。

private static final String FILE_PATH = "/etc/project/file.path";
private String decryptedPassword = "";

@Autowired
public ClassToBeTested(@Value("${pass}") String encryptedPassword)
{
    String decryptedPassword = StaticClass.decrypt(encryptedPassword, FILE_PATH);
}

我需要在 JUnit 测试中以某种方式模拟这个文件,以便我可以测试其余的功能。 @Before 注释没有用,因为根据我的测试,即使是在 Bean 初始化之后运行。

可以使用的一种非常肮脏的方法是向 Autowired 函数添加另一个参数,该参数可以指示调用是否用于单元测试。但这确实不是一个干净的方法。例如:

private static final String FILE_PATH = "/etc/project/file.path";
private String decryptedPassword = "";

@Autowired
public ClassToBeTested(@Value("${pass}") String encryptedPassword,
        @Value("${isTest}") boolean isTest)
{
    if (isTest)
        decryptedPassword = encryptedPassword;
    else
        decryptedPassword = StaticClass.decrypt(encryptedPassword, FILE_PATH);
}

有什么想法可以在 FILE_PATH 模拟文件,这样我就不必在不更改 Bean 构造函数的情况下使用此解决方法或强制 Autowired 函数中的属性?

【问题讨论】:

  • 重构类以将PasswordSupplier 或类似的注入其中。
  • 我尝试了一种方法来创建一个类来处理解密并在测试设置中模拟它。如果密码解密不在 bean 的构造函数中,则此方法有效。但是,就我而言,由于遗留代码问题,它必须在构造函数中。
  • 那你就完蛋了,因为如果无法获取文件,构造函数会抛出异常。尽可能重构。也许你可以添加一个更健全的构造函数?

标签: java spring unit-testing junit javabeans


【解决方案1】:

您可以使用 Whitebox 之类的工具来交换测试上下文中的 FILE_PATH。

public class MyClass {
   private static  String MY_STRING = "hello";

   public void whatsMyString() {
       System.out.println(MY_STRING);
   }
}

请注意,MY_STRING 不是最终的

@Test
    public void testWhiteboxSwap() {
        MyClass test = new MyClass();
        test.whatsMyString();

        String testContextString = "\tgoodbye";
        Whitebox.setInternalState(MyClass.class, testContextString);
        test.whatsMyString();
    }

控制台输出:

hello
    goodbye

您可能仍需要在测试结构中使用 @Before@BeforeClass 来获得正确的时间,但 Whitebox 可以促进您正在寻找的行为。

请注意,这不是线程安全的解决方案。如果多个测试更改静态引用,最后一个将获胜!

我的示例使用了一个 Maven 项目。我在下面附上了 pom 添加。

<dependency>
    <groupId>org.powermock.tests</groupId>
    <artifactId>powermock-tests-utils</artifactId>
    <version>1.5.4</version>
</dependency>

【讨论】:

    【解决方案2】:

    在我的具体情况下,我发现的唯一方法是重构代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      • 2011-05-21
      • 2018-12-06
      • 2022-01-19
      • 2011-08-04
      相关资源
      最近更新 更多