autowore mockmvc is null in controller test after I upgrade spring framework to 6.0.1 - spring

using:
springboot version is 3.0.1
spring framework version 6.0.1
java version 17
after I upgrade my spring framework version, I refactor security configuration to this
#WebMvcTest(NominationController.class)
#AutoConfigureMockMvc
class NominationIsolationTest extends Specification {
#Autowired
MockMvc mockMvc
...
def "should return status created with response when post nominations given valid nomination"() {
given:
...
when:
def response = mockMvc")
.content(body).contentType(MediaType.APPLICATION_JSON))
then:
...
}
but it failed, and I debug find that the mockMvc' value is null, and I use spock to do the controller test
I have try to add #SpringBootTest annotation, but not work
before I upgrade, the controller test can run successfully

now I fixed this issue, by add #ContextConfiguration annotation on test class, and autowire WebApplicationContext then use mvcbuilder to create mockmvc, after that, it fixed
#WebMvcTest
#ContextConfiguration
class IsolationTest extends Specification {
#Autowired
WebApplicationContext wac
MockMvc mockMvc
def setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build()
}

Related

Integration Testing With #DataJpaTest

I have this test in my project:
#DataJpaTest
#SpringBootTest
#TestPropertySource(locations = "classpath:local-configuration.properties")
public class CanPixaRepositoryTest {
#Autowired
private CanPixaRepository canPixaRepository;
public void setUp() throws Exception {
}
#Test
public void testAll() {
canPixaRepository].getAvui("fqs");
}
}
local-configuration.properties:
spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
but when I run the test, canPixaRepositoryRepository is null
For Spring boot applications, the simplest approach is using #DataJpaTest with H2 to test your repositories if you are using JPA and Spring Data JPA.
Add h2 dependency into your test scope. Spring Boot will auto-configure it and use it to replace the runtime DataSource in the testing phase.
Annotate your tests with #DataJpaTest. Then the EntityManager, your repositories, and a test-purpose TestEntityManager are available in the Spring Application Context.
Check my example here.
(Spring 5/Spring Boot 2 added Junit 5 support, it does not require the #Runwith or #Extendwith if you are using Junit 5 integration, the DataJpaTest itself is a meta-annotation, before Spring 2.4, to enable Junit5, you have to exclude JUnit 4 from spring-boot-test and add JUnit 5 manually. In the upcoming Spring Boot 2.4, JUnit 5 is the default test runner)
#SpringBootTest annotation is used to setup the entire application context while the #DataJpaTest will setup the application context so that you could test your jpa related code, it will setup a slice of your application context for this specific use case .So there is no need to use the #SpringBootTest annotation with #DataJpaTest, use it like :
#ExtendWith(SpringExtension.class)
#DataJpaTest
#TestPropertySource(locations = "classpath:local-configuration.properties")
public class CanPixaRepositoryTest {
#Autowired
private CanPixaRepository canPixaRepository;
public void setUp() throws Exception {
}
#Test
public void testAll() {
canPixaRepository.getAvui("fqs");
}
}
Since SpringBoot 2.1 you don't have to provide the #ExtendWithannotation to tell Junit to enable spring support as it is already provided with the annotations like #SpringBootTest and #DataJpaTest.

Spring boot 2.2.4 spy bean integration test is not a Mockito mock

In my free time I'm migrating from spring boot 1.5 to newsest (2.2.4). I think I'm pretty close to the end. Having this dependencies:
org.mockito:mockito-core:2.28.2
org.mockito:mockito-junit-jupiter:2.18.3
com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0
org.springframework.boot:spring-boot-starter-test:2.2.4.RELEASE
Currently forcing problem probably with #SpyBean
#RunWith(SpringRunner::class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class abc {
#SpyBean
lateinit var abcRepository: AbcRepository
enter code here
...
#Test
fun test {
...
val abcCaptor = ArgumentCaptor.forClass(Abc::class.java)
verify(abcRepository, times(2)).save(abcCaptor.capture())
}
And the error is. As I can see in debug department repository is Proxy -> SimpleJpaRepository
VerificationStartedEvent.setMock() does not accept parameter which is not a Mockito mock.
Received parameter: org.springframework.data.jpa.repository.support.SimpleJpaRepository#7f48943b.
See the Javadoc.

Spring Boot 2.1/2.2 testing - how to test a single controller without creating beans for everything else?

Before in Spring Boot 2.0 I had something like:
#RunWith(SpringRunner::class)
#DataJpaTest
#AutoConfigureMockMvc
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
#ActiveProfiles("unit-test")
#SpringBootTest
#WithUserDetails
class MyControllerTest {
#InjectMocks
lateinit var myController: MyController
lateinit var mvc: MockMvc
#Before
fun setup() {
mvc = MockMvcBuilders.standaloneSetup(myController).build()
}
...
But after trying to upgrade to Spring Boot 2.1, I get various random errors, such as:
WithUserDetails not working: java.lang.IllegalStateException: Unable to create SecurityContext using #org.springframework.security.test.context.support.WithUserDetails(value=user, userDetailsServiceBeanName=, setupBefore=TEST_METHOD)
Irrelevant beans were (attempting) to be created: kotlin.UninitializedPropertyAccessException: lateinit property <property> has not been initialized - this was from a #ConfigurationProperties class.
and a few more other stuff that just didn't make sense to me (in 2.2, I can't have both #DataJpaTest and #SpringBootTest together either).
Does anyone have an idea for what I would need to do to correctly update these unit tests?
You use either a sliced test #WebMvcTest or a full integration test with #SpringBootTest. Hence it has no sense in using them together. In your case you want to test a controller, then use the #WebMvcTest and mock the dependencies.
#RunWith(SpringRunner::class)
#WebMvcTest(MyController.class)
#WithUserDetails
class MyControllerTest {
#Autowired
lateinit var myController: MyController
#Autowired
lateinit var mvc: MockMvc
#MockBean
var myService: MyServiceForController
Use #MockBean to mock the service dependencies for the controller and register behavior on it. You can now also simply wire the controller and a pre-setup MockMvc instance instead of wiring that yourself.

Spring boot cucumber testing

I try to perform some Cucumber tests of a Spring boot application.
It seems like Spring Boot is not started before tests are running.
What am i missing?
https://bitbucket.org/oakstair/spring-boot-cucumber-example
My Cucumber repo still runs without doing all the above steps:
https://github.com/BarathArivazhagan/Cucumber-spring-integration
Docs : https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
To add more:
#SpringBootTest takes care of loading the application context in that case #ContextConfiguration is reductant.
Spring test automatically provides a bean of TestRestTemplate which can be autowired but still it should work with RestTemplate also.
It still runs without RANDOM_PORT but RANDOM port can be also used in conjunction for testing.
Let's say you have a feature file, feature1, and glueCode in org.xyz.feature1
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"pretty"},
features = "src/test/java/resources/feature/feature1",
glue = {"org.xyz.feature1"})
public class CucumberTest {
}
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {Application.class},
webEnvironment = WebEnvironment.RANDOM_PORT)
#ContextConfiguration
#Ignore
#Transactional
public class FeatureTest extends CucumberTest {
#LocalServerPort
int randomServerPort;
#Given("........")
public void test_1 {
}
}
I found the problem and has updated the repo.
I did the following to get it working:
Added RANDOM_PORT to #SpringBootTest
Added #ContextConfiguration
Switched from RestTemplate to TestRestTemplate

WebApplicationContext is always null when running Geb integration test

Why isn't my context being injected? The application runs fine. Integration tests using Spring's junit runner and MockMvc run fine. Do I need to add something to integrate Spring and Spock?
#ContextConfiguration(classes = MyConfiguration)
#WebAppConfiguration
class BetaRequestTest extends GebReportingSpec{
#Autowired
WebApplicationContext webApplicationContext; //always null
def setup() {
browser.driver = MockMvcHtmlUnitDriverBuilder
.webAppContextSetup(webApplicationContext).build()
}
def destroy(){
browser.driver?.close()
}
#Test
def void "should render the page"(){
setup:
to BetaRequestPage
expect:
$('h1').value() == "Welcome to Foo"
}
}
Figured it out.
I needed to add the following test dependency:
testCompile "org.spockframework:spock-spring:1.0-groovy-2.4"

Resources