Grails单元测试:通过grailsApplication访问定义的bean

Grails unit tests: Accessing defined beans via grailsApplication

我有一些(非Grails-artifact)类,它们通过在grailsApplication对象周围传递来访问服务层bean。 但是,我无法对以这种方式实现的类进行单元测试。 为什么未在主上下文中注册Bean?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@TestMixin(GrailsUnitTestMixin)
class ExampleTests {
  void setUp() {}

  void tearDown() {}

  void testSomething() {
    defineBeans {
      myService(MyService)
    }

    assert grailsApplication.mainContext.getBean("myService") != null
  }
}

上面的代码失败并显示:

org.springframework.beans.factory.NoSuchBeanDefinitionException:未定义名为" myService"的bean

我想做的是通过grailsApplication从普通的旧Java类访问服务。 这有效,但在单元测试环境中不起作用。 我应该以其他方式做吗?

1
2
3
4
5
6
7
class POJO {
  MyService myService;

  public POJO(GrailsApplication grailsApplication) {
    myService = (MyService) grailsApplication.getMainContext().getBean("myService");
  }
}

答案是在GrailsUnitTestMixin中,将保存您的bean的applicationContext设置为grailsApplication中的parentContext

1
2
3
4
5
6
7
beans.registerBeans(applicationContext)

static void initGrailsApplication() {
...
//the setApplicationContext in DefaultGrailsApplication set's the parentContext
grailsApplication.applicationContext = applicationContext
}

因此,您可以通过以下方式获取豆类:

1
2
3
4
5
6
defineBeans {
  myService(MyService)
}

assert applicationContext.getBean("myService")
assert grailsApplication.parentContext.getBean("myService")

编辑

今天,我遇到了同样的问题,我的解决方案是:

1
2
3
4
@Before
void setup() {
  Holders.grailsApplication.mainContext.registerMockBean("myService", new MyService())
}


在我的情况下(2.4.4版),接受的解决方案不起作用,但为我指明了正确的方向,因为在我的单元测试中mainContext中的bean工厂是OptimizedAutowireCapableBeanFactory,所以这一行有效

1
Holders.grailsApplication.mainContext.beanFactory.registerSingleton('myBean', new MyBeanClass())


我花了一些时间处理相同的问题,以我的情况运行grails 2.2.4并具有(在src / groovy中):

1
2
3
4
5
import grails.util.Holders
class SomeClass {
  transient myService = Holders.grailsApplication.mainContext.getBean 'myService'
  .....
}

这与问题作者有点不同,但至少对来自搜索引擎结果的人有用

尽管如此,接受的答案对我来说不起作用,所以我想出了一些与SomeClass中使用的模拟和注册服务不同的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import grails.util.Holders
.. other imports
@TestMixin(GrailsUnitTestMixin)
class SomeClassTests {
    @Before
    void setUp() {
        Holders.grailsApplication = grailsApplication
        defineBeans {
            myService(MyServiceMock)
        }
    }
    ....
}

class MyServiceMock extends MyService {
  // overriden methods here
}