如何对使用springSecurityService的控制器进行单元测试? [英] How to unit test controllers that use springSecurityService?

查看:420
本文介绍了如何对使用springSecurityService的控制器进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  class User {
transient springSecurityService
String displayName
字符串密码
< snip>
protected void encodePassword(){
password = springSecurityService.encodePassword(password)
}
}

UserController
我试图为 UserController 编写单元测试,但是我收到了保存,更新和删除测试的错误:

  java.lang.NullPointerException:无法在null对象上调用方法encodePassword()

我必须通过嘲弄的方式来设置这项功能吗?



我尝试了许多组合嘲笑代码如下,但我很茫然。

  defineBeans {
springSecurityService(SpringSecurityService)

$ / code>

任何建议都将不胜感激。

解决方案

我个人不喜欢在产品代码中添加逻辑来帮助满足测试。有时你必须决定什么是最好的。几个选项...


  1. 上面的答案是可行的,但正如我所说我个人不喜欢

  2. 不要单元测试。将所有运行到这种情况的测试写入集成测试。

  3. 用假服务模拟它。

如果将此代码(或运行相同问题的代码)分散到整个应用程序中,那么您可能需要找出一种方法在单元测试中模拟所有测试用例中的这些调用,以便您不要在任何地方复制你的设置。一个简单的方法就是用metaClassing。

  @Test 
public void something(){
def user = ...
def springSecurityService = new Object()
springSecurityService.metaClass.encodePassword = {String password - > ENCODED_PASSWORD}
user.springSecurityService = springSecurityService
...
}

现在,当调用 springSecurityService.encodePassword 时,它应该返回ENCODED_PASSWORD。我也创建了一个 Object ,而不是实例化一个新的 SpringSecurityService ,因为如果你实例化一个实际的服务,那么你最终可能会调用那些服务的实际方法会出乎意料且不知不觉,并让您的测试通过错误的原因。我宁愿得到一个没有这样的方法错误,而不是通过不应该传递的测试。


I have a user class like such:

class User {
    transient springSecurityService
    String displayName
    String password
<snip>
    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
}

And a UserController. I'm trying to write unit tests for the UserController however I'm getting this error for save, update and delete tests:

java.lang.NullPointerException: Cannot invoke method encodePassword() on null object

What do I have to set up in the way of mocking to get this to work?

I have tried many combinations of mocking code such as the following, but I am at a loss.

defineBeans {
    springSecurityService(SpringSecurityService)
}

Any advice would be greatly appreciated.

解决方案

I personally don't like adding logic to production code to help satisfy a test. Sometimes you have to make a decision on what's best to do. Couple of options...

  1. The above answer will work, but as I stated I personally wouldn't prefer
  2. Don't unit test. Write all of your tests that run into this situation as integration tests.
  3. Mock it out with a fake service.

If this code (or code that runs into the same problem) is sprinkled throughout your application then you'd probably want to figure out a way to mock out these calls in your unit tests for all test cases so you're not duplicating your setup efforts everywhere. An easy way to mock this out is with metaClassing.

@Test
public void something() {
   def user = ...
   def springSecurityService = new Object()
   springSecurityService.metaClass.encodePassword = {String password -> "ENCODED_PASSWORD"}
   user.springSecurityService = springSecurityService
   ...
}

Now when the springSecurityService.encodePassword gets invoked it should return "ENCODED_PASSWORD". I also create an Object instead of instantiating a new SpringSecurityService because if you instantiate an actual service then you may end up calling actual methods on that service unexpectedly and unknowingly and having your tests pass for the wrong reasons. I'd rather get a no such method error than a passing test that shouldn't be passing.

这篇关于如何对使用springSecurityService的控制器进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆