java - 测试组件类

标签 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:种子 = 1 预期:83T81EOKK3ZZB259U5 实际:Z49G2RLF0HJNNWZQCP

最佳答案

what can I do for the randomPasswordTest, test if the class returns a random string ?

你必须消除随机性。

最好的方法是通过 依赖注入(inject) 传递 Random 类的实例。然后您可以为您的测试传递一个类型为 Random 的测试替身

这个测试替身 可能是使用模拟框架创建的模拟

另一方面,Java 的 Random 类是一个伪随机生成器。 这意味着从修复种子开始,它将始终产生相同的数字序列。因此,您可以简单地创建一个 Random 实例,并将修复种子作为您的测试替身:

Random predictableValueProducer= new Random(1); 

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


i don't know how to go about it, can you show how it should look like ?

被测代码

@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);
    }
}

for some reason they are not fixed

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

删除这一行:

    Random rnd = new Random();

并改变这个:

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

还有你误用random.nextInt() 应该是

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

正如我已经建议的那样。

I tried to use the annotation @inject it came from dozer library and did not work , what library does that annotation belong to [...] I tried to use @Autowire but it shows no bean of type random – valik

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

关于java - 测试组件类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48519278/

相关文章:

java - 为什么我的 JFrame 无法绘制?

python - 如果 __init__ 方法设置了类的公共(public)属性,您是否对其进行单元测试?

Python单元测试模拟,获取模拟函数的输入参数

java - 是否可以在站点生命周期内只运行 JaCoCo maven 插件?

sql - 架构更改脚本 : Validation and test cases

java - 通过外部网关发送 SMS 的设计评论

java - 不可变对象(immutable对象)如何帮助减少垃圾收集带来的开销?

java - Websphere 是否尊重守护进程线程?

php - $this->dispatch ('/' ) 在 zend 测试中意味着什么

python - 我可以在 Django 测试中避免 permission_required 装饰器吗?