如何在JUnit测试中初始化时模拟Bean所需的文件

时间:2016-07-25 16:52:40

标签: java spring unit-testing junit javabeans

我有一个正在初始化时读取文件的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注释没有用,因为即使是根据我的测试在Beans初始化之后运行。

可以使用的一种非常脏的方法是向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函数中的属性?

2 个答案:

答案 0 :(得分:3)

您可以使用 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>

答案 1 :(得分:0)

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