I want to test a grails application(using jaxrs) and it's integrations. For this task I hope to use the awesome IntegrationTestCase-class from the jaxrs plugin.
This is challenging because I want to mock/replace a service within my application. With “pure” Spring I would create testcontext and manually wire up the mock. I have no idea how to do this in grails.
I’ve tried to access the ApplicationContext directly
Holders.grailsApplication.mainContext.registerMockBean("myService", new MyMock())
This does not seem to work as the mock is not used during the test. Any ideas?
Try to define in test class his way:
#Before
void before() {
Holders.grailsApplication = grailsApplication
defineBeans {
myService(MyMock)
}
}
It's for jUnit tests. If you use Spock, rename before() to setup() and see Spock basics Fixture Methods.
Related
I am new to Spring and spring boot.
For my spring boot application which is a rest controller, I have some beans along with my data source.
I use my data source to create jdbc template. Now when I am in my rest controller code, I have all these beans #Autowired and they work perfectly fine.
My query is regarding the junit testing part.
When I write my test code inside src/test/java and when I execute my test class within IDE, are the beans defined in my src/main/javacode, instantiated before test case execution?
You might use the same container, or instantiate another container particularly for testing purposes, for which you'll provide a configuration of that other Spring Container separately:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:test-context.xml")
public class SomeClassTest{...}
However, you can also enable support for loading your Application Context and then use the #Autowired fields in your JUnit fixtures, which also works fine too:
#RunWith(SpringRunner.class)
public class SomeTestClass {
....
#Autowired
ApplicationContext context;
....
}
From here, you can get any bean you wish.
I am having some issues with testing my camel context with spring boot.
I am using spring boot 1.5.6, spock 1.1-groovy-2.4, camel 2.19.2, and camel-spring-boot-starter 2.19.2.
I am using a spock mock, and I'm using the DetachedMockFactory in a #TestConfiguration class. All of my beans use constructor injection. I am injecting a mocked #Repository into one of the processor #Components, and I am also injecting it into my test class to define interactions.
I have my test annotated with #SpringBootTest with the classes list including all Processor implementations, and all RouteBuilder extensions. I also have an '#Import' with my TestConfiguration class. I am even using constructor injection for this repository bean in my test!
But it seems that the mock that is injected into the test class is not the one that is in use. Does anyone have an idea what could be wrong? I have tried #DirtiesContext to reload the context both before and after each test, but that did not help.
Problems with DetachedMocks not behaving correctly, e.g., appearing to be the same instance, are usually caused by some framework wrapping them in proxies. For example this can be caused by #Transactional annotation in Spring, which creates a proxy to facilitate jdbc-session management. See also issue #758
For spring you can use the methods of AopUtils (jdoc). The simple way is to use AopUtils.isAopProxy to check if it is proxied by spring an then unwrap it.
public static <T> T getTargetObject(Object proxy) throws Exception {
if (AopUtils.isAopProxy(proxy)) {
return (T) ((Advised) proxy).getTargetSource().getTarget();
} else {
return (T) proxy;
}
}
And in a Test
def "sample service test"() {
given:
def sampleRepositryMock = getTargetObject(sampleRepositry)
when:
sampleService.doSomething() // simply invoke sampleRepositry.doSomething() in it
then:
1 * sampleRepositryMock.doSomething()
0 * _
}
Edit: Since Spock 1.2 there is an extension to automatically unwrap injected beans #UnwrapAopProxy.
#Inject
#UnwrapAopProxy
SampleRepositry sampleRepositryMock
If someone comes up with the same problem.
Spock added additional #UnwrapAopProxy that will do the job for you instead of the util method mentioned above. You can also drop the DetachedMockFactory
#SpringSpy
#UnwrapAopProxy
Service service
I'm using Spring Rest Docs to generate documentation for my REST services. This involves running unit(strictly integration) tests that run against a live Spring Boot Container that is kicked off by the test. The test class looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = MySpringConfiguration.class)
#WebAppConfiguration
public class ApiDocumentation {
private MockMvc mockMvc;
#Rule
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");
#Autowired
private WebApplicationContext context;
#Autowired
private ObjectMapper objectMapper;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration(this.restDocumentation))
.build();
}
#Test
public void testSomething() throws Exception {
}
}
The application uses JPA with EclipseLink for the EntityManager implementation.
When I run the test standalone in my IDE or as the only test present when I run a Maven build using the maven-surefire-plugin everything works fine.
However it's not the only test I want to run in the suite. As soon as I run other tests in the suite I come across the issue mentioned here, namely
"Spring's agent does not initialize the persistence context until the application accesses the Spring context. If the application has already triggered the loading of the persistent class before accessing the Spring context, weaving will not occur."
and get errors like this:
Exception Description: The method [_persistence_set_someField_vh] or [_persistence_get_someField_vh] is not defined in the object [mypackage.MyEntity].
So what do people normally do to get around this ? Run SpringBootTest classes in a different module to unit tests that access entities ?
As far as I concerned problem caused by dynamic weaving, if you make it static it should work proper. Possibly it could help you
Another solution could be to disable dynamic weaving in that particular test using eclipselink.weaving JPA property.
See this question and its answers: #SpringBootTest interferes with EclipseLink dynamic weaving
I have a Spring based application and am in the process of unit testing it. I'm using TestNG for unit tests. For my test i need to make use of PowerMockito to mock some static methods. I also need to make use of a test spring config file for only my unit test.
I'm unable to write my unit tests combining all the three i.e. TestNg, PowerMock and Spring.
I can combine TestNG and Spring by extending the class AbstractTestNGSpringContextTests, however cant mock static methods, instead it executes the actual static method. Something like the below:
#PrepareForTest(MyUtils.class)
#ContextConfiguration(locations = { "classpath:config/test-context.xml"})
public class MyImplTest extends AbstractTestNGSpringContextTests{
.....
}
I can combine TestNG with PowerMockito by extending the class PowerMockTestCase. But then the test spring config files are not resolved. Something like the below:
#PrepareForTest(MyUtils.class)
#ContextConfiguration(locations = { "classpath:config/test-context.xml"})
public class MyImplTest extends PowerMockTestCase{
.....
}
Is there any way for me to write my unit tests combining all the three, i.e. TestNg, PowerMockito and Spring context?
Rather than extending PowerMockTestCase, have you tried using the PowerMockObjectFactory by writing a method like below? Then you can extend AbstractTestNGSpringContextTests.
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
This is suggested by the Powermock GitHub docs.
I am new to Spring-boot.
We are trying to practice spring-boot-test by adding the following Java class in this Spring guide for testing purpose.
However, it turns out that we are not able to trigger this Java class. In other words, there is no any test result showing up in the our eclipse console.
Could someone suggest us where we do wrong?
Thanks!
GreetingControllerTest.java
package hello;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest
public class GreetingControllerTest {
private RestTemplate restTemplate = new RestTemplate();
#Test
public void testGreeting() {
System.out.println("Where is my TEST?????!!!!!!");
String url = "http://localhost:8080/greeting";
assertNotNull(restTemplate.getForObject(url, Greeting.class));
}
}
The Spring Framework does not run (trigger) tests. Rather, a testing framework like JUnit or TestNG runs tests.
Your code appears to be fine. So, assuming that the example you supplied compiles (i.e., has the correct package imports) and assuming that the #Test annotation you have declared is #org.junit.Test, then you simply need to run the test as a JUnit test.
Your IDE (e.g., Eclipse, IntelliJ, NetBeans) and build framework (e.g., Maven, Ant, Gradle) should provide support for running JUnit tests.
Regards,
Sam