You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've provided a very simple sbt project that reproduces this problem. by-name-repro.zip
In the reproduction project, similar to my actual scenario but simplified, the scenario is as follows:
I have a class we can call DataManager that I want to test. It's methods all follow a similar pattern of:
classDataManager {
/** * Perform admin operations if the user is allowed to perform them * @paramdata admin data * @paramsecurityPolicy the security policy to check users access * @paramuserRole the current users role * @return*/defdoAdminStuff(
data: String
)(
implicitsecurityPolicy: SecurityPolicy,
userRole: UserRole
):Future[Int] =
securityPolicy.withRole(UserRole.ADMIN) {
println("Performing admin operation")
Future(1)
}
}
The implicit Security policy is what I'm mocking in my tests and then testing a normal instance of the Data Manager
The security policy uses curried operations of the following form:
/** * Run the specified operation only if the expectedRole is equal to the users role * @paramexpectedRole the required role to execute the operation * @paramoperation the operation to perform * @paramuserRole the users actual role * @return the result of the operation or throws an exception if unauthorized*/defwithRole(expectedRole: UserRole)(operation: =>Future[Int])(implicituserRole: UserRole) =if (expectedRole == userRole)
operation
elsethrownewException(s"must have $expectedRole to perform this operation")
The operation should only ever be evaluated if the security check passes.
The following tests will fail because the operation is evaluated even though the security policy's mocked answer is executed correctly:
test("Admin operation should not be called with user role") {
implicitvalsecurityPolicy:SecurityPolicy= mock[SecurityPolicy]
valdataManager=newDataManager()
// by-name parameter evaluation are implemented by wrapping in a Function0
{ (role: UserRole, operation: Function0[Future[Int]], userRole: UserRole) =>thrownewException("Access denied")
} willBe answered by securityPolicy.withRole(eqTo(UserRole.ADMIN))(any[Future[Int]])(
any[UserRole]
)
intercept[Exception] {
implicitvaluserRole:UserRole=UserRole.USERAwait.result(dataManager.doAdminStuff("test"), Duration.Inf)
}
assert(dataManager.adminOperationCount ==0)
}
However if I wrap the DataManager instance in a spy then the same test will pass as the operation isn't executed:
test("using spy, Admin operation should not be called with user") {
implicitvalsecurityPolicy:SecurityPolicy= mock[SecurityPolicy]
valdataManager= spy(newDataManager())
// by-name parameter evaluation are implemented by wrapping in a Function0
{ (role: UserRole, operation: Function0[Future[Int]], userRole: UserRole) =>thrownewException("Access denied")
} willBe answered by securityPolicy.withRole(eqTo(UserRole.ADMIN))(any[Future[Int]])(
any[UserRole]
)
doCallRealMethod().when(dataManager).doAdminStuff(anyString)(any[SecurityPolicy], any[UserRole])
doCallRealMethod().when(dataManager).adminOperationCount
intercept[Exception] {
implicitvaluserRole:UserRole=UserRole.USERAwait.result(dataManager.doAdminStuff("test"), Duration.Inf)
}
assert(dataManager.adminOperationCount ==0)
}
The text was updated successfully, but these errors were encountered:
I've provided a very simple sbt project that reproduces this problem.
by-name-repro.zip
In the reproduction project, similar to my actual scenario but simplified, the scenario is as follows:
I have a class we can call
DataManager
that I want to test. It's methods all follow a similar pattern of:The implicit Security policy is what I'm mocking in my tests and then testing a normal instance of the Data Manager
The security policy uses curried operations of the following form:
The operation should only ever be evaluated if the security check passes.
The following tests will fail because the operation is evaluated even though the security policy's mocked answer is executed correctly:
However if I wrap the DataManager instance in a spy then the same test will pass as the operation isn't executed:
The text was updated successfully, but these errors were encountered: