Are there any ways to simplify those codes?

I’m using Kotlin and SpringBoot to write a website. I wrote these codes for my DAOs testing.

       //Change Password
        userDao.createUser("test5", "Test 5", "123456".toByteArray())
        val changePasswordSalt = userDao.getLoginSalt("test5")
        Assertions.assertEquals(userDao.changePassword("test5", genHashedPassword("111111".toByteArray(), changePasswordSalt), "222222".toByteArray()), false)
        Assertions.assertEquals(userDao.changePassword("test5", genHashedPassword("123456".toByteArray(), changePasswordSalt), "654321".toByteArray()), true)
        userDao.deleteAll()

        //Change Nick Name
        userDao.createUser("test6", "Test 6", "123456".toByteArray())
        val changeNickNameSalt = userDao.getLoginSalt("test6")
        Assertions.assertEquals(userDao.changeNickName("test6", genHashedPassword("111111".toByteArray(), changeNickNameSalt), "6 Test"), false)
        Assertions.assertEquals(userDao.changeNickName("test6", genHashedPassword("123456".toByteArray(), changeNickNameSalt), "6 Test"), true)
        userDao.deleteAll()

        //Change Permission
        userDao.createUser("test7", "Test 7", "123456".toByteArray())
        val changePermissionSalt = userDao.getLoginSalt("test7")
        Assertions.assertEquals(userDao.changePermission("test7", genHashedPassword("111111".toByteArray(), changePermissionSalt), true), false)
        Assertions.assertEquals(userDao.changePermission("test7", genHashedPassword("123456".toByteArray(), changePermissionSalt), true), true)
        userDao.deleteAll()

Could I simplify these codes? If I can, What should I do?

I think your code would be more readable if you would put more logic into your User object. The responsibility of a “DAO” is typically persistence and not mutating the object to be persisted or read.

It is unclear to me, why the hashed password should be passed to a DAO to change a nickname. The DAO is then not only responsible for changing the domain object User, but also for authentication! I’d suggest the following:

  • User: (in context of security): hold and mutate nickname and password, check password
  • DAO: Save and find Users
  • UserService: perform authorization (maybe through a Spring Security annotation)

But apart from that, you could use more lightweight assertions like AssertJ (medium weight :wink:) or some Kotlin assertion library like the one from Kotest.

I hope that the code above is from three different test functions. If that is the case, you can remove the deleteAll call, since a @SpringBootTest runs in a transaction that is rolled back after the test.

However, I suggest to take a step back and think about what you really want to test. Let’s say you want to change the password, then you could

  • create a user and set a password
  • change the password
  • check, if the user can be authenticated with this password (no need to compare the password itself)

My fictional test case would look like this:

@Test
fun `should change password`() { 
    val user = User("Harry", "secret")
    
    user.changePassword("secret", "new secret")

    user.authenticate("new secret") shouldBe true
}

In this case you wouldn’t need persistence (and hence no Spring integration test - a usual unit test would be enough). The salt is an implementation detail and must not be provided from the outside (it is enough if the user object knows the salt).

2 Likes

Thanks, medium.
I’m new to SpringBoot and Kotlin, I will check out Kotest and rethink my code.