测试组件类

时间:2018-01-30 10:33:43

标签: java unit-testing testing

我有一个类似于此的类,它是我的应用程序中使用的组件

@Component
public class SecurityUtility {

    private final String SALT = "salt";

    Random random;


    public SecurityUtility(Random random) {
        this.random = random;
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12, new SecureRandom(SALT.getBytes()));
    }

    public String randomPassword() {
        String SALTCHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";

        StringBuilder stringBuilder = new StringBuilder();
        Random rnd = new Random();

         while (stringBuilder.length() < 18) {
            int index =   rnd.nextInt() * SALTCHARS.length();
            stringBuilder.append(SALTCHARS.charAt(index));
        }
        String randPass = stringBuilder.toString();

        return randPass;
    }
}

我可以做些什么来测试这样的课程,我该怎么做呢,通常我一直在进行单元测试,但是这个课程,不知道什么类型的测试或如何去做。提前感谢您的任何建议。单位或任何其他测试。

使用固定种子进行测试

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = SecurityUtility.class)
public class SecurityUtilityTest {

    @MockBean
    Random random;

    @Test
    public void createRandomPasswordSeed() {

          random = new Random(1 );

        String randomPassword = new SecurityUtility(random).randomPassword();

        Assert.assertEquals("seed = 1" , "83T81EOKK3ZZB259U5" , randomPassword );
    }

错误

org.junit.ComparisonFailure:seed = 1 预计:83T81EOKK3ZZB259U5 实际:Z49G2RLF0HJNNWZQCP  

1 个答案:

答案 0 :(得分:2)

  

我可以为randomPasswordTest做些什么,测试该类是否返回一个随机字符串?

你必须删除随机性。

最好的方法是通过依赖注入传递类Random的实例。然后,您可以为测试传入Random类型的 test double

测试双可能是使用模拟框架创建的模拟

另一方面,Javas Random类是伪随机生成器。 这意味着从修复种子开始,它将始终生成相同的数字序列。因此,您只需使用修复种子创建Random实例作为 test double

Random predictableValueProducer= new Random(1); 

您可以在另一个测试方法中使用不同的种子并检查更改的输出,以确保您的代码确实使用传入的Random对象。

  

我不知道如何去做,你能说明它应该是什么样的吗?

正在测试的代码

@Component
public class SecurityUtility {
    private final String SALT = "salt";
    private final Random random;

    // I prefer constructor injection...
    public SecurityUtility(@Inject Random random){
         this.random = random ;
    }
    @Bean
    public String randomPassword() {
        String SALTCHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        StringBuilder salt = new StringBuilder();        
        while (salt.length() < 18) {
            int index = random.nextInt(SALTCHARS.length());
            salt.append(SALTCHARS.charAt(index));
        }
        return  salt.toString();
    }
}

测试

public class SecurityUtilityTest {

    @Test
    public void createsRandomPasswordWithSeed1() {
        // arrange
        Random randomWithFixSeed = new Random(1);

        // act
        String randomPassword = 
           new SecurityUtility(randomWithFixSeed).randomPassword();

        // assert
        assertEquals("seed = 1", "83T81EOKK3ZZB2S9U5", randomPassword);
    }

    @Test
    public void createsRandomPasswordWithSeed2() {
        Random randomWithFixSeed = new Random(2);

        String randomPassword = 
           new SecurityUtility(randomWithFixSeed).randomPassword();

        assertEquals("seed = 2", "EYUT8GG2HYCC95OIH2", randomPassword);
    }
}
  

由于某种原因,他们没有修复

测试仍然失败,因为您未完成“测试中的代码”所需的更改。它仍在Random内创建一个新的randomPassword()对象,而不是使用您引入的成员变量。

删除此行:

    Random rnd = new Random();

并改变这一点:

        //int index =   rnd.nextInt() * SALTCHARS.length();
        int index =   random.nextInt() * SALTCHARS.length();

你也错过random.nextInt()它应该是

        int index =   random.nextInt(SALTCHARS.length());

正如我已经建议的那样。

  

我试图使用它来自dozer库的注释@inject并没有用,该注释属于哪个库[...]我尝试使用@Autowire但它没有显示任意类型的bean - valik < / p>

注释与测试问题无关。它们在初始化阶段在应用程序运行时发挥作用。