工厂方法模式是否可能没有抽象方法?(Is Factory Method pattern without abstract methods possible?)
假设一个没有抽象方法的Java程序,是否可以在没有抽象方法的情况下实现Factory Method模式?
Let's say one Java program that does not have abstract methods, is it possible to implement the Factory Method pattern without abstract methods?
原文:https://stackoverflow.com/questions/19255288
最满意答案
从官方复数页面复制了一些代码提取
要进行身份验证的端点位于
config/routes.rb
post 'authenticate', to: 'authentication#authenticate'
执行此操作。 如果您正确进行身份验证,操作将返回令牌。
def authenticate command = AuthenticateUser.call(params[:email], params[:password]) if command.success? render json: { auth_token: command.result } else render json: { error: command.errors }, status: :unauthorized end end
在rspec中,您有两个选项,您可以模拟此方法或创建工厂。
token based
身份验证的概念是,一旦经过身份验证,用户将拥有令牌,并且通过提供此令牌,他将能够访问仅保留给用户的功能请求
$ curl -H "Content-Type: application/json" -X POST -d '{"email":"example@mail.com","password":"123123123"}' http://localhost:3000/authenticate
作为回应令牌
{"auth_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0NjA2NTgxODZ9.xsSwcPC22IR71OBv6bU_OGCSyfE89DvEzWfDU0iybMA"}
如果您在标头中包含令牌,请求将不会触发授权错误
$ curl -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0NjA2NTgxODZ9.xsSwcPC22IR71OBv6bU_OGCSyfE89DvEzWfDU0iybMA" http://localhost:3000/items []
所以在执行get请求之前,请在请求标头中包含令牌
request.headers['Authorization'] = auth_token get :your_action
如何提供正确的
auth_token
值?您需要在
ApplicationController
模拟authenticate_request
方法,因为它在action
before
被调用#app/controllers/application_controller.rb class ApplicationController < ActionController::API before_action :authenticate_request attr_reader :current_user private def authenticate_request @current_user = AuthorizeApiRequest.call(request.headers).result render json: { error: 'Not Authorized' }, status: 401 unless @current_user end end
我相信你应该模拟这行代码,以避免收到身份验证错误。
@current_user = AuthorizeApiRequest.call(request.headers).result
所以我会写一些像这样的规格
user = FactoryBot.create(:user) allow(AuthorizeApiRequest).to receive(:call).and_return(user) # request.headers['Authorization'] = auth_token # this is not required anymore the authentication is skipped get :your_action
我引用了复数
通过使用before_action,每次用户发出请求时,服务器都会将
request headers
(使用内置对象属性request.headers)传递给AuthorizeApiRequest
。 在AuthorizeApiRequest.call(request.headers)
上调用result
来自SimpleCommand
模块,其中定义为attr_reader :result
。 请求结果将返回给@current_user
,从而可供从ApplicationController
继承的所有控制器使用。你可以阅读更多关于嘲笑的内容
Some Code Extracts copied from the the official pluralsight page
the endpoint to authenticate is in
config/routes.rb
post 'authenticate', to: 'authentication#authenticate'
which executes this action. The action returns the token if you correctly authenticate.
def authenticate command = AuthenticateUser.call(params[:email], params[:password]) if command.success? render json: { auth_token: command.result } else render json: { error: command.errors }, status: :unauthorized end end
In rspec you have two options, you either mock this method or create a factory.
The concept of
token based
authentication is that once authenticated the user will have a token and by providing this token he will be able to access the functionalities only reserved to usersThe request
$ curl -H "Content-Type: application/json" -X POST -d '{"email":"example@mail.com","password":"123123123"}' http://localhost:3000/authenticate
gives in response the token
{"auth_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0NjA2NTgxODZ9.xsSwcPC22IR71OBv6bU_OGCSyfE89DvEzWfDU0iybMA"}
if you include in the header the token, the request will not trigger an authorization error
$ curl -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0NjA2NTgxODZ9.xsSwcPC22IR71OBv6bU_OGCSyfE89DvEzWfDU0iybMA" http://localhost:3000/items []
so before doing your get request, include in the request header the token
request.headers['Authorization'] = auth_token get :your_action
How to provide a correct value of
auth_token
?You will need to mock the method
authenticate_request
inApplicationController
, as it is calledbefore
theaction
#app/controllers/application_controller.rb class ApplicationController < ActionController::API before_action :authenticate_request attr_reader :current_user private def authenticate_request @current_user = AuthorizeApiRequest.call(request.headers).result render json: { error: 'Not Authorized' }, status: 401 unless @current_user end end
I believe you should mock this line of code, to avoid receiving an authentication error.
@current_user = AuthorizeApiRequest.call(request.headers).result
so I would write the specs somethind like this
user = FactoryBot.create(:user) allow(AuthorizeApiRequest).to receive(:call).and_return(user) # request.headers['Authorization'] = auth_token # this is not required anymore the authentication is skipped get :your_action
I quote pluralsight
By using before_action, the server passes the
request headers
(using the built-in object property request.headers) toAuthorizeApiRequest
every time the user makes a request. Callingresult
onAuthorizeApiRequest.call(request.headers)
is coming fromSimpleCommand
module where it is defined asattr_reader :result
. The request results are returned to the@current_user
, thus becoming available to all controllers inheriting fromApplicationController
.You can read more about mocking at
相关问答
更多-
从官方复数页面复制了一些代码提取 要进行身份验证的端点位于config/routes.rb post 'authenticate', to: 'authentication#authenticate' 执行此操作。 如果您正确进行身份验证,操作将返回令牌。 def authenticate command = AuthenticateUser.call(params[:email], params[:password]) if command.success? render ...
-
Rspec轨道测试设计邮件(Rspec rails test devise mailer)[2022-06-11]
尝试: expect(confirmation_email.body.encoded).to include 'You can confirm your account email' Try: expect(confirmation_email.body.encoded).to include 'You can confirm your account email' -
当单个规范的执行成功但同一规范在作为较大套件的一部分运行时失败时,它表示其他测试的先前执行正在影响结果。 如果有问题的规范是深层嵌套的,就像在这种情况下,隔离问题的一种方法是从相关规范中运行连续目录中的所有规范,直到导致失败。 一旦找到导致问题的目录,就可以通过指定在失败测试之前运行的不同系列规范来进一步隔离,直到您找出有问题的规范。 例如,在这种情况下,您将运行rspec spec/requests/api/v1 ,如果成功,则运行rspec spec/requests/api ,如果成功则运行rspec ...
-
如何在RSpec测试中为JSON API传递身份验证令牌?(How to pass authentication token in RSpec test for JSON API?)[2022-04-18]
像这样使用它: get '/api/v1/projects/1', {}, { Authorization: "Token 123"} get是http方法, {}是一个空的参数, { :Authorization => "Token 123"}标题 get(path,parameters = nil,headers_or_env = nil) Documentation 另一种方式: before do # some code here @request.env['Authoriza ... -
我最后重构了很多其他代码来运行在实际控制器中创建实例变量的身份验证方法。 我不相信有一种方法可以在Rspec中设置变量以用于GET请求。 使用集成测试来测试authenticate_with_http_token ,您需要在GET请求中包含它: get '/v1/path-for-api', nil, authorize: 'Token token=#{user.token}' 从那里开始,变量已经正确设置,我能够测试请求。 I ended up refactoring quite a bit of oth ...
-
似乎POST参数是JSON编码的。 795: unexpected token at 'myparam'当应用程序尝试JSON解码未编码的参数时,会导致795: unexpected token at 'myparam' 。 使用.to_json和post params。 post api_v1_post_path(@myid), {"myparam" => "myvalue"}.to_json , {"X-Some-Header" => "MyValue"} 您可能想要使用let: describe ' ...
-
将auth令牌添加到默认标头与使用$ http拦截器(Adding auth token to default headers vs. using $http interceptors)[2022-08-09]
在对Reddit进行了大量研究和对话后 ,似乎最好的方法就是通过拦截器。 在.config或.run块中进行设置可能有助于检查用户在首次加载应用程序时是否已经过身份验证(如果本地存储中有令牌),但无法处理动态更改,例如在加载应用程序后注销或登录。 我很确定你可以通过$ http默认标头来实现,但也可以在一个地方进行。 希望这有助于未来的人! After a bunch more research and a conversation on Reddit, it seems like the best way ... -
起初,我以这种方式创建了网络应用上下文 mockMvc = webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); 但解决方案是获取SessionRepositoryFilter过滤器的实例并将其添加到Web应用程序上下文中。 过滤器负责返回x-auth-token标头。 SessionRepositoryFilter> filter = webApplicationContext.getBean(Sessi ...
-
正确的答案是避免非常复杂的观点。 如果视图中几乎没有逻辑,那么可能没有必要对其进行测试。 将逻辑提取到演示者中 ,这样就可以更容易地进行测试。 我没有使用视图测试来测试我的视图,因为维护它们通常不是很有趣。 一些功能规格在这里给了我足够的安全性。 如果您仍想测试它,您可能希望使用预期的参数调用render : expect(view).to receive(:render).with(@employee.contacts) 不确定视图是否可通过view 。 PS:不要只是避免编写复杂的视图,避免复杂的代码 ...
-
nil的未定义方法`response':NilClass rspec测试(undefined method `response' for nil:NilClass rspec test)[2022-03-08]
it { should respond_with 401 }没有指定哪个对象应该用401响应,这就是错误的原因。 要修复它,请尝试: expect(response).to respond_with 401 或使用主题 : subject{ response } it { should respond_with 401 } it { should respond_with 401 } does not specify which object should repond with 401, that ...