Junit5 Contorller Test with SpringbootTest can’t load method getParameterName() - junit5

version:spring-boot-starter-test 2.2.12.RELEASE
When I run junit5 test,I want test controller。
there is code
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = RuoYiApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
public abstract class BaseTest {
#SpyBean
TokenService mockTokenService;
#Autowired
public MockMvc mockMvc;
#Autowired
public TestRestTemplate restTemplate;
public class CommonControllerTest extends BaseTest {
#SpyBean
CommonController commonController;
#Autowired
private MockMvc mockMvc;
#Test
public void testFileDownloadNotExists() throws URISyntaxException {
String fileName = "...";
URI uri = UriComponentsBuilder
.fromUriString("/common/download")
.queryParam("fileName", fileName)
.build()
.encode()
.toUri();
RequestEntity<Void> downloadRequest = RequestEntity
.get(uri).accept(MediaType.APPLICATION_JSON).build();
ResponseEntity<String> response = restTemplate.getForEntity(downloadRequest.getUrl(), String.class);
assertThat(response.getBody()).isEqualTo(null);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
When the request send to controller,It can't get method ParameterNames,it alos run inspectClass function read class information,but without ParameterNames and The program enter the breakpoint inspectClass read nothing becase of wrong path(com/**/CommonController$MockitoMock$1821216982.class).
It normal when I run SpringBoot Application,it can enter the breakpoint inspectClass read class inputstream。
How solve this problem?
when I change the mockito version from 3.1.0 to 3.6.28 this com/**/CommonController$MockitoMock$1821216982.class changed to
com.ruoyi.web.controller.common.CommonController

Related

Cannot read properties when used MockWebServer

Hi I am new to the Junit Testing and am trying to test the third party call, for that I have used MockWebServer from okhttp3, the mockWebServer does the job of giving me a proper mocked response but in the class that I am trying to test has the following
#Autowired
Environment env
....
...
..
String url = env.getProperty(shop.url);
The above is significant as it gets the url from application.yml
But the env is null whenever I am running that particular test method which uses MockWebServer
Main Class
Class ConnectionService {
#Autowired
Environment environment;
public ConnectionService(WebClient.Builder builder) {
this.webClient = builder.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.baseUrl(usersBaseUrl).build();
}
public void getShops(){
...
..
String url = env.getProperty(shop.url);
..
..
}
Test Class
#ExtendWith(SpringExtension.class)
#SpringBootTest
#AutoConfigureWireMock(port = 0)
class ConnectionServiceTest {
public static MockWebServer mockWebServer;
private static ConnectionService connectionService;
#BeforeAll
public static void setUp() throws IOException {
mockWebServer = new MockWebServer();
connectionService = new ConnectionService(WebClient.builder(),
mockWebServer.url("/").toString();
}
#AfterAll
static void tearDown() throws IOException {
mockWebServer.shutdown();
}
#Test
void testMethod() {
MockResponse mockResponse = new MockResponse()
.addHeader("Content-Type", "application/json; charset=utf-8")
.setBody("{\"status\":\"up\",\"details\":\"details\"}")
.throttleBody(16, 5, TimeUnit.SECONDS);
mockWebServer.enqueue(mockResponse);
connectionService.getShops();
}
}
Could someone please help me out figure what am I doing wrong, is it the MockWebServer that is causing environment to be null ? even the other properties in other files are null. Thanks in advance :)
I tried to test the WebClient by making use of MockWebServer, although it worked but now I cannot read any properties either from application.yml or otherProperties.properties as the environments variables are not getting injected

java.lang.NullPointerException: null on AutoWiring a bean in StandAlone App

When trying to use #AutoWire feature with one of StandAlone Application unable to do so instead getting Null Pointer Exception. Please highlight my mistakes if any. Your help is appreciated.
Spring Ver 5.1.5.RELEASE and we're not using any xml config file to tell spring there are annotated classes to look into instead using #ComponentScan or #EnableAutoConfiguration at the top of AppConfig and boost strap the Context from main() class as a first line. But Autowiring works perfectly with internal bean/java classes of jdk(Environment) but not with custom POJO classes. If we're trying to get through getBean method then it works. But I'm trying to avoid creating context everywhere and using getBean() Please Refer below and help me only with your valuable guidelines.
public class ContextMaster {
private static AnnotationConfigApplicationContext appContext;
public static AnnotationConfigApplicationContext getApplicationContext() {
if (appContext == null) {
appContext = new AnnotationConfigApplicationContext(ContextConfig.class);
//appContext = new AnnotationConfigApplicationContext("com.xx.xx.xxx","xx.xxx.xxxx.xxx.datamanager");
logger.debug("Context Invoked !!");
}
return appContext;
}
}
#Configuration
#EnableAutoConfiguration
#PropertySource("classpath:db.properties")
#EnableTransactionManagement
#ComponentScans(value = {
#ComponentScan(basePackages = "xxxxx.datamanager"),
#ComponentScan(basePackages = "com.xx.xx.xxx"),
#ComponentScan(basePackages = "com.xx.xx.xxx.utils")})
public class AppConfig {
#Autowired
private Environment env;
#Bean
public DataSource getDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("db.driver"));
dataSource.setUrl(env.getProperty("db.url"));
return dataSource;
}
#Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
//LocalSessionFactoryBean sessionFactoryBean = new AnnotationSessionFactoryBean();
factoryBean.setDataSource(getDataSource());
Properties props=new Properties();
props.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
props.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
props.put("hibernate.cache.region.factory_class", env.getProperty("hibernate.cache.region.factory_class"));
factoryBean.setHibernateProperties(props);
factoryBean.setAnnotatedClasses(xx.class, xxxx.class, xxxx.class, xxx.class);
return factoryBean;
}
#Bean
public HibernateTransactionManager getTransactionManager() {
return transactionManager;
}
}
// Here is NPE thrown when tried with auto-configured bean
#Component
public class Good extends Good11 {
#Autowired
private RxxxDyyyyHelper rdh;
//RxxxDyyyyHelper rdh =
ContextHelper.getApplicationContext().getBean(RxxxDyyyyHelper .class);
rdh.setProperty(); // NPE here
rdh.getProperty(); // NPE
}
// Here we're trying to initiate the LosUtils class
public class LosUtils {
public static void main(String args[]) throws Exception {
AnnotationConfigApplicationContext applicationContext = `ContextHelper.getApplicationContext();`
}
It seems like you didn't put the full code here, because your Good class won't compile this way..

Replace #Value property within #Configuration during Spring Boot test

Scenario
I've got a Spring Boot application with a #Configuration annotated Spring configuration class which contains some #Value annotated fields. For testing I want to replace these field values with custom test values.
Unfortunately these test values cannot be overridden using a simple properties file, (String) constants or similar, instead I must use some custom written property resolving Java class (e.g. TargetProperties.getProperty("some.username")).
The problem I have is that when I add a custom PropertySource to the ConfigurableEnvironment within my test configuration, it's already too late because this PropertySource will be added after the e.g. RestTemplate has been created.
Question
How can I override #Value annotated fields within a #Configuration class with properties obtained programmatically via custom Java code before anything else gets initialized?
Code
Production Configuration Class
#Configuration
public class SomeConfiguration {
#Value("${some.username}")
private String someUsername;
#Value("${some.password}")
private String somePassword;
#Bean
public RestTemplate someRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(
new BasicAuthorizationInterceptor(someUsername, somePassword));
return restTemplate;
}
}
Test Configuration Class
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class SomeTest {
#SpringBootConfiguration
#Import({MySpringBootApp.class, SomeConfiguration.class})
static class TestConfiguration {
#Autowired
private ConfigurableEnvironment configurableEnvironment;
// This doesn't work:
#Bean
#Lazy(false)
// I also tried a #PostConstruct method
public TargetPropertiesPropertySource targetPropertiesPropertySource() {
TargetPropertiesPropertySource customPropertySource =
new TargetPropertiesPropertySource();
configurableEnvironment.getPropertySources().addFirst(customPropertySource);
return customPropertySource;
}
}
}
You can override properties directly in the #SpringBootTest annotation using the properties parameter:
#SpringBootTest(properties = {"some.username=user", "some.password=pwd"},
webEnvironment = SpringBootTest.WebEnvironment.NONE)
You can use #TestPropertySource
#TestPropertySource(
properties = {
"some.username=validate",
"some.password=false"
}
)
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationTest {
//...
}
You can use constructor injection in production cases, which allows it to set the configuration manually:
#Configuration
public class SomeConfiguration {
private final String someUsername;
private final String somePassword;
#Autowired
public SomeConfiguration(#Value("${some.username}") String someUsername,
#Value("${some.password}") String somePassword) {
this.someUsername = someUsername;
this.somePassword = somePassword;
}
...
)
}
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class SomeTest {
private SomeConfiguration config;
#Before
public init() {
config = new SomeConfiguration("foo", "bar");
}
}

How to use arquillian to test EJB calling webservices using #webserviceref annotation

I'm trying to use arquillian to test one method of an EJB using a webservice through #WebServiceRef annotation
In my method decorated by #Deployment I declared the resource
#Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class)
.addPackages(true, .... PortType.class.getPackage())
.addAsResource("test-my.wsdl","my.wsdl")
.addAsManifestResource("META-INF/beans.xml", "beans.xml").addAsManifestResource("META-INF/test-persistence.xml", "persistence.xml");
}
Then I coded the bean as following
#Stateless
#LocalBean
public class WSBean {
#WebServiceRef(wsdlLocation = "/my.wsdl")
PortType portType;
public void test() throws Exception{
portType.lireAdresseClient(null, null);
}
}
and the test
#RunWith(Arquillian.class)
public class WSintegrationTest extends DefaultServicesIntegrationTest {
#Deployment
....
#Inject
private WSBean wsBean;
#Test
public void testAppel() throws Exception {
System.out.println("TEST APPEL");
wsBean.test();
}
}
Can I do that with Arquillian ?
How can I fix it ?
Thanks
Regards
Also if you want you can take a look at https://github.com/javaee-samples/javaee7-samples/tree/master/jaxws you will find examples of JAXWS with its Arquillian test.

Arquillian with Mockito and CDI

Is it possible to create spy(mock) object in testing class?
Here is tested class.
#Stateless
#Slf4j
public class UserDao {
#Inject
private TestBean testBean;
public String mock() {
return testBean.mock();
}
public String notMock() {
return testBean.notMock();
}
}
TestBean code
#Stateless
#Slf4j
public class TestBean {
public String notMock() {
return "NOT MOCK";
}
public String mock() {
return "IMPLEMENTED MOCK";
}
}
Here's my test
#RunWith(Arquillian.class)
public class UserDataTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Inject
private UserDao userDao;
#Deployment
protected static Archive createWar() {
File[] dependencies = Maven.configureResolver()
.withRemoteRepo("nexus-remote", "http://maven.wideup.net/nexus/content/groups/public/", "default")
.withRemoteRepo("nexus-release", "http://maven.wideup.net/nexus/content/repositories/releases/", "default")
.resolve(
"org.slf4j:slf4j-simple:1.7.7",
"eu.bitwalker:UserAgentUtils:1.15",
"org.mockito:mockito-all:1.10.8"
).withoutTransitivity().asFile();
return ShrinkWrap
.create(WebArchive.class, "pass.jpa.war")
.addAsWebInfResource("jbossas-ds.xml")
.addAsWebInfResource("jboss-deployment-structure.xml")
.addAsLibraries(
PassApiDeployments.createDefaultDeployment(),
PassUtilLibrary.createDefaultDeployment(),
PassJpaDeployments.createDefaultDeployment()
).addAsLibraries(dependencies);
}
#Test
public void testMock() {
assertEquals("MOCK", userDao.mock());
}
#Test
public void testNotMock() {
assertEquals("NOT MOCK", userDao.notMock());
}
}
I'd like to create a spy object on TestBean to change result on method test() of this bean.
So is it possible to create TestBean spy in UserDao.
I solve some problems through producer like this.
#Singleton
public class MockFactory {
#Produces
#ArquillianAlternative
public TestBean getTestBean() {
return when(mock(TestBean.class).mock()).thenReturn("MOCK").getMock();
}
}
But in this example I need create on Bean completely on my own. And if it is bean with additional dependencies and thus i will manage all dependencies.
As far as I know, its not possible to use a mocking framework in combination with arquillian ...
I haven't used it myself, but this Arquillian extension seems to be specifically designed to support Mockito Spy objects in an Arquillian test: https://github.com/topikachu/arquillian-extension-mockito/