I am new to Junit. Recently, I need add some test function for a spring web project.
So I add a new project only for testing.
Firstly, I add a test case for testing ADServiceImpl, and following is my test code.
#Test
public void test() {
ADServiceImpl service = new ADServiceImpl();
UserInfo info = service.getUserInfo("admin", "123456");
assertEquals("Result", "00", info.getStatus().getCode());
}
After I run the test and got a error is that 'endpoint' is null. But 'endpoint' is setting by spring #Resource(name = "adEndpoint") from xml configuration.
How can I deal with this problem?? Or is there other recommend for spring web project testing? Thank you so much!
#Service("ADService")
public class ADServiceImpl implements ADService {
private final static Logger logger = Logger.getLogger(ADServiceImpl.class);
#Resource(name = "adEndpoint")
private String endpoint;
public UserInfo getUserInfo(String acc, String pwd) throws JAXBException, RemoteException {
if (StringUtils.isBlank(endpoint)) {
logger.error("***** AD Endpoint is blank, please check sysenv.ad.endpoint param ******");
}
ADSoapProxy proxy = new ADSoapProxy();
proxy.setEndpoint(endpoint);
logger.debug("***** AD endpoint:" + endpoint + "******");
String xml = proxy.userInfo(acc, pwd);
StringReader reader = new StringReader(xml);
JAXBContext jaxbContext = JAXBContext.newInstance(UserInfo.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
return (UserInfo) jaxbUnmarshaller.unmarshal(reader);
}
}
When creating Unit Tests that requires Spring to be running you need to add the following to your unit test class. For example:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MySpringApp.class)
public MyTestClass{
#Test
...
}
More info here
Related
I need to test some REST client. For that purpose I'm using org.mockserver.integration.ClientAndServer
I start my server. Create some expectation. After that I mock my client. Run this client. But when server receives request I see in logs:
14:00:13.511 [MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - received binary request:
505249202a20485454502f322e300d0a0d0a534d0d0a0d0a00000604000000000000040100000000000408000000000000ff0001
14:00:13.511 [MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - unknown message format
505249202a20485454502f322e300d0a0d0a534d0d0a0d0a00000604000000000000040100000000000408000000000000ff0001
This is my test:
#RunWith(PowerMockRunner.class)
#PrepareForTest({NrfClient.class, SnefProperties.class})
#PowerMockIgnore({"javax.net.ssl.*"})
#TestPropertySource(locations = "classpath:test.properties")
public class NrfConnectionTest {
private String finalPath;
private UUID uuid = UUID.fromString("8d92d4ac-be0e-4016-8b2c-eff2607798e4");
private ClientAndServer mockServer;
#Before
public void startMockServer() {
mockServer = startClientAndServer(8888);
}
#After
public void stopServer() {
mockServer.stop();
}
#Test
public void NrfRegisterTest() throws Exception {
//create some expectation
new MockServerClient("127.0.0.1", 8888)
.when(HttpRequest.request()
.withMethod("PUT")
.withPath("/nnrf-nfm/v1/nf-instances/8d92d4ac-be0e-4016-8b2c-eff2607798e4"))
.respond(HttpResponse.response().withStatusCode(201));
//long preparations and mocking the NrfClient (client that actually make request)
//NrfClient is singleton, so had to mock a lot of methods.
PropertiesConfiguration config = new PropertiesConfiguration();
config.setAutoSave(false);
File file = new File("test.properties");
if (!file.exists()) {
String absolutePath = file.getAbsolutePath();
finalPath = absolutePath.substring(0, absolutePath.length() - "test.properties".length()) + "src\\test\\resources\\test.properties";
file = new File(finalPath);
}
try {
config.load(file);
config.setFile(file);
} catch(ConfigurationException e) {
LogUtils.warn(NrfConnectionTest.class, "Failed to load properties from file " + "classpath:test.properties", e);
}
SnefProperties spyProperties = PowerMockito.spy(SnefProperties.getInstance());
PowerMockito.doReturn(finalPath).when(spyProperties, "getPropertiesFilePath");
PowerMockito.doReturn(config).when(spyProperties, "getProperties");
PowerMockito.doReturn(config).when(spyProperties, "getLastUpdatedProperties");
NrfConfig nrfConfig = getNrfConfig();
NrfClient nrfClient = PowerMockito.spy(NrfClient.getInstance());
SnefAddressInfo snefAddressInfo = new SnefAddressInfo("127.0.0.1", "8080");
PowerMockito.doReturn(nrfConfig).when(nrfClient, "loadConfiguration", snefAddressInfo);
PowerMockito.doReturn(uuid).when(nrfClient, "getUuid");
Whitebox.setInternalState(SnefProperties.class, "instance", spyProperties);
nrfClient.initialize(snefAddressInfo);
//here the client makes request
nrfClient.run();
}
private NrfConfig getNrfConfig() {
NrfConfig nrfConfig = new NrfConfig();
nrfConfig.setNrfDirectConnection(true);
nrfConfig.setNrfAddress("127.0.0.1:8888");
nrfConfig.setSnefNrfService(State.ENABLED);
nrfConfig.setSmpIp("127.0.0.1");
nrfConfig.setSmpPort("8080");
return nrfConfig;
}
}
Looks like I miss some server configuration, or use it in wrong way.
Or, maybe the reason is in powermock: could it be that mockserver is incompatible with powermock or PowerMockRunner?
I am having issue when I deploy the jar in AWS ubuntu server,I have 2 packages in Spring Boot.
#1)core package
#2)Process package
The first package(core) is not containing spring boot dependency and generate the jar using maven package,When I run the code the below code works fine in Intellij. But when I deploy in AWS Ubuntu machine I get Null Pointer Exception for MySQLAdapter Class used in the Process PackageController.
Below is the code
//Code in Process
#SpringBootApplication
public class ProcessApplication
{
#Bean
MySQLAdapter mySQLAdapter() {
MySQLAdapter mySQLAdapter = new MySQLAdapter();
return mySQLAdapter;
}
public static void main(String[] args) {
SpringApplication.run(com.test.ProcessApplication.class, args);
}
}
// Core package jar
public class MySQLAdapter {
private String hostName;
private int port;
private String DBName;
private String username;
private String pwd;
private String secretPwdKey;
private com.test.Util.CryptoUtil cryptoUtil;
public MySQLAdapter() {
hostName = "localhost";
port = 3306;
username = "test";
pwd = "test";
DBName = "test";
secretPwdKey = "test";
cryptoUtil = new com.test.Util.CryptoUtil();
}
}
Is this Null Pointer Exception because of cryptoUtil not getting injected or instantiated?
How can this be solved?
// Controller inside Process package
#RestController
class MyRestController{
#Autowired
MySQLAdapter mySQLAdapter;
#RequestMapping(value = {"/register"}, method = {RequestMethod.POST}, produces = {"application/json"})
#ResponseBody
public RegistrationResponse register(#Valid #RequestBody UserPojo userPojo) {
if (!this.mySQLAdapter.checkClientID(userPojo.getClientID())) { //Null Pointer thrown here
}
}
}
Our project is not currently using a spring framework.
Therefore, it is being tested based on the standalone tomcat runner.
However, since integration-enabled tests such as #SpringBootTest are not possible, Tomcat is operated in advance and the HTTP API test is carried out using Spock.
Is there a way to turn this like #SpringBootTest?
TomcatRunner
private Tomcat tomcat = null;
private int port = 8080;
private String contextPath = null;
private String docBase = null;
private Context rootContext = null;
public Tomcat8Launcher(){
init();
}
public Tomcat8Launcher(int port, String contextPath, String docBase){
this.port = port;
this.contextPath = contextPath;
this.docBase = docBase;
init();
}
private void init(){
tomcat = new Tomcat();
tomcat.setPort(port);
tomcat.enableNaming();
if(contextPath == null){
contextPath = "";
}
if(docBase == null){
File base = new File(System.getProperty("java.io.tmpdir"));
docBase = base.getAbsolutePath();
}
rootContext = tomcat.addContext(contextPath, docBase);
}
public void addServlet(String servletName, String uri, HttpServlet servlet){
Tomcat.addServlet(this.rootContext, servletName, servlet);
rootContext.addServletMapping(uri, servletName);
}
public void addListenerServlet(ServletContextListener listener){
rootContext.addApplicationListener(listener.getClass().getName());
}
public void startServer() throws LifecycleException {
tomcat.start();
tomcat.getServer().await();
}
public void stopServer() throws LifecycleException {
tomcat.stop();
}
public static void main(String[] args) throws Exception {
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
System.setProperty(javax.naming.Context.URL_PKG_PREFIXES, "org.apache.naming");
Tomcat8Launcher tomcatServer = new Tomcat8Launcher();
tomcatServer.addListenerServlet(new ConfigInitBaseServlet());
tomcatServer.addServlet("restServlet", "/rest/*", new RestServlet());
tomcatServer.addServlet("jsonServlet", "/json/*", new JsonServlet());
tomcatServer.startServer();
}
Spock API Test example
class apiTest extends Specification {
//static final Tomcat8Launcher tomcat = new Tomcat8Launcher()
static final String testURL = "http://localhost:8080/api/"
#Shared
def restClient
def setupSpec() {
// tomcat.main()
restClient = new RESTClient(testURL)
}
def 'findAll user'() {
when:
def response = restClient.get([path: 'user/all'])
then:
with(response){
status == 200
contentType == "application/json"
}
}
}
The test will not work if the annotations are removed from the annotations below.
// static final Tomcat8Launcher tomcat = new Tomcat8Launcher()
This line is specified API Test at the top.
// tomcat.main()
This line is specified API Test setupSpec() method
I don't know why, but only logs are recorded after Tomcat has operated and the test method is not executed.
Is there a way to fix this?
I would suggest to create a Spock extension to encapsulate everything you need. See writing custom extensions of the Spock docs as well as the built-in extensions for inspiration.
I'm developing a webservice using Dropwizard JDBI framework.
Now, instead of having a db configurations in yaml file, I want to use 'user specified params' what i mean to say is, the db configs will be provided through the endpoint url.
Is having custom creds possible through dropwizard jdbi?
if yes, what changes should i be thinking to do in the code while referring this ? ->
http://dropwizard.readthedocs.org/en/latest/manual/jdbi.html
I understand, in normal flow, the service method gets the config details in the run method -
-- Config Class
public class ExampleConfiguration extends Configuration {
#Valid
#NotNull
#JsonProperty
private DatabaseConfiguration database = new DatabaseConfiguration();
public DatabaseConfiguration getDatabaseConfiguration() {
return database;
}
}
-- Service Class
#Override
public void run(ExampleConfiguration config,
Environment environment) throws ClassNotFoundException {
final DBIFactory factory = new DBIFactory();
final DBI jdbi = factory.build(environment, config.getDatabaseConfiguration(), "postgresql");
final UserDAO dao = jdbi.onDemand(UserDAO.class);
environment.addResource(new UserResource(dao));
}
-- and yaml
database:
# the name of your JDBC driver
driverClass: org.postgresql.Driver
# the username
user: pg-user
# the password
password: iAMs00perSecrEET
# the JDBC URL
url: jdbc:postgresql://db.example.com/db-prod
But in this case, I might get the config details in the Resource level...
smthing like -
#GET
#Path(value = "/getProduct/{Id}/{dbUrl}/{dbUname}/{dbPass}")
#Produces(MediaType.APPLICATION_JSON)
public Product getProductById(#PathParam(value = "Id") int Id,
#PathParam(value = "dbUrl") String dbUrl,
#PathParam(value = "dbUname") String dbUname,
#PathParam(value = "dbPath") String dbPass) {
//I have to connect to the DB here! using the params i have.
return new Product(); //should return the Product
}
I'd appreciate if someone can point me a direction.
Why not just use JDBI directly?
#GET
#Path(value = "/getProduct/{Id}/{dbUrl}/{dbUname}/{dbPass}")
#Produces(MediaType.APPLICATION_JSON)
public Product getProductById(#PathParam(value = "Id") int id,
#PathParam(value = "dbUrl") String dbUrl,
#PathParam(value = "dbUname") String dbUname,
#PathParam(value = "dbPass") String dbPass) {
DataSource ds = JdbcConnectionPool.create(dbUrl, dbUname, dbPass);
DBI dbi = new DBI(ds);
ProductDAO dao = dbi.open(ProductDao.class);
Product product = dao.findById(id);
dao.close();
ds.dispose();
return product;
}
#RegisterMapper(ProductMapper.class)
static interface ProductDao {
#SqlQuery("select id from product_table where id = :id") // Whatever SQL query you need to product the product
Product findById(#Bind("id") int id);
#SqlQuery("select * from product_table")
Iterator<Product> findAllProducts();
}
static class ProductMapper implements ResultSetMapper<Product> {
public Product map(int index, ResultSet r, StatementContext ctx) throws SQLException {
return new Product(r.getInt("id")); // Whatever product constructor you need
}
}
There's a notion in the spring world of using a database router (reference: https://spring.io/blog/2007/01/23/dynamic-datasource-routing/).
You likely could setup a proxy for the database connection factory passed to DBI. That proxy would then get the credentials from a thread local (perhaps) and return the real connection giving you what you're after and still let you use the run type proxies.
I try to create a soap UI WSDL Mock Service using the soapUI API. But there seems to be no documentation of the source code.
Has anyone done this before or something in that direction?
Ok, I can now answer myself ... :)
I created a unit test for this task:
private static WsdlProjectFactory wsdlProjectFactory;
private static WsdlInterfaceFactory wsdlInterfaceFactory;
#BeforeClass
public static void createFactories(){
wsdlProjectFactory = new WsdlProjectFactory();
wsdlInterfaceFactory = new WsdlInterfaceFactory();
}
#Before
public void deleteCreatedFiles() {
new File("global-groovy.log").delete();
new File("soapui-errors.log").delete();
new File("soapui.log").delete();
new File("test.xml").delete();
}
private WsdlProject project;
#Before
public void createProject() throws XmlException, IOException, SoapUIException {
project = wsdlProjectFactory.createNew();
}
#Test #Ignore
public void testWSDLInterfaceImporting() throws SoapUIException {
int interfaceCount = project.getInterfaceCount();
assertThat("newly created project has no interfaces", interfaceCount, is(equalTo(0)));
WsdlInterface[] importWsdl = wsdlInterfaceFactory.importWsdl(project, "wsdls/SimpleUseCasesellerbtainitialbtexampleMasterClient.wsdl", false);
interfaceCount = project.getInterfaceCount();
assertThat("newly created project has 1 interface", interfaceCount, is(equalTo(1)));
}
#Test
public void testMockCreation() throws XmlException, IOException, SoapUIException {
int mockCount = project.getMockServiceCount();
assertThat("newly created project has no mocks", mockCount, is(equalTo(0)));
WsdlInterface[] importWsdl = wsdlInterfaceFactory.importWsdl(project, "wsdls/SimpleUseCasesellerbtainitialbtexampleMasterClient.wsdl", false);
WsdlMockService service = project.addNewMockService("newMockService");
service.addNewMockOperation(importWsdl[0].getOperationAt(0));
project.saveAs("test.xml");
mockCount = project.getMockServiceCount();
assertThat("project has exactly one mock", mockCount, is(1));
}