Lau*_*vas 5 unit-testing scala slick
我有一个要对它进行单元测试的方法:
@Singleton
class RegistrationWorkflow @Inject()(userService: UserService,
addUserValidator: RegisterUserValidator,
db: Database) {
def registerUser(registerForm: RegisterUserForm): Future[Vector[FormError]] = {
val dbActions = addUserValidator.validate(registerForm).flatMap({ validation =>
if (validation.isEmpty) {
userService.add(User(GUID.shortGuid(),
registerForm.username,
registerForm.email,
BCrypt.hashpw(registerForm.password, BCrypt.gensalt())))
.andThen(DBIO.successful(validation))
} else {
DBIO.successful(validation)
}
}).transactionally
db.run(dbActions)
}
}
Run Code Online (Sandbox Code Playgroud)
addUserValidator验证表单并返回Vector表单错误。如果没有错误,则将用户插入数据库。我正在返回表单错误,因为在控制器中我将返回带有错误列表的201或400。
我为此编写了一个specs2测试:
class RegistrationWorkflowTest extends Specification with Mockito with TestUtils {
"RegistrationControllerWorkflow.registerUser" should {
"insert a user to database if validation succeeds" in new Fixture {
registerUserValidatorMock.validate(testUserFormData) returns DBIO.successful(Vector())
userServiceMock.add(any) returns DBIO.successful(1)
val result = await(target.registerUser(testUserFormData))
result.isEmpty must beTrue
there was one(registerUserValidatorMock).validate(testUserFormData)
there was one(userServiceMock).add(beLike[User] { case User(_, testUser.username, testUser.email, _) => ok })
}
"return error collection if validation failed" in new Fixture {
registerUserValidatorMock.validate(testUserFormData) returns DBIO.successful(Vector(FormError("field", Vector("error"))))
val result = await(target.registerUser(testUserFormData))
result.size must beEqualTo(1)
result.contains(FormError("field", Vector("error"))) must beTrue
there was one(registerUserValidatorMock).validate(testUserFormData)
there was no(userServiceMock).add(any)
}
}
trait Fixture extends Scope with MockDatabase {
val userServiceMock = mock[UserService]
val registerUserValidatorMock = mock[RegisterUserValidator]
val target = new RegistrationWorkflow(userServiceMock, registerUserValidatorMock, db)
val testUser = UserFactory.baseUser()
val testUserFormData = RegisterUserFactory.baseRegisterUserForm()
}
}
Run Code Online (Sandbox Code Playgroud)
该测试的问题在于它仅断言已userService.add被调用。这意味着我可以将实现更改为以下内容:
val dbActions = addUserValidator.validate(registerForm).flatMap({ validation =>
if (validation.isEmpty) {
userService.add(User(GUID.shortGuid(),
registerForm.username,
registerForm.email,
BCrypt.hashpw(registerForm.password, BCrypt.gensalt())))
DBIO.successful(validation)
} else {
DBIO.successful(validation)
}
}).transactionally
db.run(dbActions)
Run Code Online (Sandbox Code Playgroud)
测试仍然可以通过,但是不会插入用户,因为我没有andThen在userService.add方法返回的DBIO上使用组合器。
我知道我可以使用内存数据库,然后断言实际上已插入用户,但是我不想这样做,因为我已经userService.add使用内存数据库分别测试了方法,现在我想测试registerUser方法而无需调用任何方法依赖性。