Grails unit tests: Accessing defined beans via grailsApplication

非 Y 不嫁゛ 提交于 2019-12-22 14:16:12

问题


I have some (non-Grails-artifact) classes that access the service layer beans via passing around the grailsApplication object. However I'm having trouble unit testing the classes implemented in this way. Why doesn't the bean get registered in the main context?

@TestMixin(GrailsUnitTestMixin)
class ExampleTests {
  void setUp() {}

  void tearDown() {}

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

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

The above code fails with:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myService' is defined

What I'm trying to do is access services from plain old Java classes via the grailsApplication. This works, but not in unit test environment. Should I do it differently?

class POJO {
  MyService myService;

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

回答1:


The answer is that in the GrailsUnitTestMixin the applicationContext that holds your beans is set as the parentContext in the grailsApplication

beans.registerBeans(applicationContext)

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

So you can get your beans with:

defineBeans {
  myService(MyService)
}

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

EDIT

Today I faced the same problem, and my solution is:

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



回答2:


In my case (grails 2.4.4) the accepted solution didn't work but pointed me in the right direction, this line worked instead as the bean factory in the mainContext within my unit test was an OptimizedAutowireCapableBeanFactory

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



回答3:


I have spent some time with the same issue, in my case running grails 2.2.4 and having (in src/groovy):

import grails.util.Holders
class SomeClass {
  transient myService = Holders.grailsApplication.mainContext.getBean 'myService'
  .....
}

Which is a bit different to question author, but at least it will be useful for someone coming from search engine results

Nevertheless accepted answer did not work for me, so I came up with a bit different approach of mocking and registering service used in SomeClass.

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
}


来源:https://stackoverflow.com/questions/13532417/grails-unit-tests-accessing-defined-beans-via-grailsapplication

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!