How to Mock the Property File in Junit - java

I am creating a Unit test case using Junit . Now My application is Maven Based with many profile Also I am using the Values from configuration file (Property File ) which Varies from one profile to other. I want that Unit Test run will have specified properties only not the profile one when it is running the test cases.
These can be done in 2 ways
1) Either i Mock the Property File for Unit Test .( which i dont know How) .
2) Or during run time i change the property file parameter values.(Again difficult to answer) . Any help will be appreciated .

One option: use dependency injection in order to acquire a java.util.Properties object for example.
Meaning: your production code simply holds a Properties object; like:
class Foo {
private final Properties properties;
public Foo(Properties) {
this.properties = properties;
At runtime, when the class that creates Foo objects reads property files from disk, turns them into a Properties object and gives it to the Foo constructor.
In your unit test, your test code creates a Properties object and adds whatever values you require upon creating a Foo object.
The less elegant detour: make sure that your production code reads its properties from a location that gets defined at runtime. That would allow you to create custom property files in some temp directory, and then you instruct your code under test to work with those files.

Did not got your question exactly - In one side, you are saying: you don't want to use profile related values and other side you are saying: you'll need to run with specific values (do you mean runtime values or test specific values).
Now, To answer your 1st question:
1) Either i Mock the Property File for Unit Test:
you can instantiate and load a property file(test specific) and keep the required values there in that file.
2) Or during run time i change the property file parameter values:
you can mock specific property keys with values. like below:
public void shouldBuyBread() throws Exception {
//given
given(mypropertyUtil.getProperty("NUMBER_OF_BREADS")).willReturn(10);
//when
Goods goods = shop.buyBread();
//then
assertThat(goods, containBread());
}

Related

JUnit - How to unit test method that reads files in a directory and uses external libraries

I have this method that I am using in a NetBeans plugin:
public static SourceCodeFile getCurrentlyOpenedFile() {
MainProjectManager mainProjectManager = new MainProjectManager();
Project openedProject = mainProjectManager.getMainProject();
/* Get Java file currently displaying in the IDE if there is an opened project */
if (openedProject != null) {
TopComponent activeTC = TopComponent.getRegistry().getActivated();
DataObject dataLookup = activeTC.getLookup().lookup(DataObject.class);
File file = FileUtil.toFile(dataLookup.getPrimaryFile()); // Currently opened file
// Check if the opened file is a Java file
if (FilenameUtils.getExtension(file.getAbsoluteFile().getAbsolutePath()).equalsIgnoreCase("java")) {
return new SourceCodeFile(file);
} else {
return null;
}
} else {
return null;
}
}
Basically, using NetBeans API, it detects the file currently opened by the user in the IDE. Then, it loads it and creates a SourceCodeFile object out of it.
Now I want to unit test this method using JUnit. The problem is that I don't know how to test it.
Since it doesn't receive any argument as parameter, I can't test how it behaves given wrong arguments. I also thought about trying to manipulate openedProject in order to test the method behaviour given some different values to that object, but as far as I'm concernet, I can't manipulate a variable in JUnit that way. I also cannot check what the method returns, because the unit test will always return null, since it doesn't detect any opened file in NetBeans.
So, my question is: how can I approach the unit testing of this method?
Well, your method does take parameters, "between the lines":
MainProjectManager mainProjectManager = new MainProjectManager();
Project openedProject = mainProjectManager.getMainProject();
basically fetches the object to work on.
So the first step would be to change that method signature, to:
public static SourceCodeFile getCurrentlyOpenedFile(Project project) {
...
Of course, that object isn't used, except for that null check. So the next level would be to have a distinct method like
SourceCodeFile lookup(DataObject dataLookup) {
In other words: your real problem is that you wrote hard-to-test code. The "default" answer is: you have to change your production code, to make easier to test.
For example by ripping it apart, and putting all the different aspects into smaller helper methods.
You see, that last method lookup(), that one takes a parameter, and now it becomes (somehow) possible to think up test cases for this. Probably you will have to use a mocking framework such as Mockito to pass mocked instances of that DataObject class within your test code.
Long story short: there are no detours here. You can't test your code (in reasonable ways) as it is currently structured. Re-structure your production code, then all your ideas about "when I pass X, then Y should happen" can work out.
Disclaimer: yes, theoretically, you could test the above code, by heavily relying on frameworks like PowerMock(ito) or JMockit. These frameworks allow you to contol (mock) calls to static methods, or to new(). So they would give you full control over everything in your method. But that would basically force your tests to know everything that is going on in the method under test. Which is a really bad thing.

Is it possible to change citrus environmental variables after assigning them a particular values

I have code like this
System.setProperty("citrus.xml.file.name.pattern", "/**/*test.xml");
I want to change the file name pattern after loading of context file and properties file is it possible through this code
#Test #Parameters("context")
#CitrusXmlTest()
public void xmlTest(#Optional #CitrusResource TestContext context)
{
ct=context.getApplicationContext();
StandardEnvironment config= (StandardEnvironment) ct.getEnvironment();
System.out.println("111111111111"+config.getPropertySources());
MutablePropertySources msr=config.getPropertySources();
Map m=new HashMap();
m.put("citrus.xml.file.name.pattern","/**/*xyz.xml");
MapPropertySource mps=new MapPropertySource("systemProperties", m);
msr.addFirst(mps);
}
after this test case i have a another test case like this
#CitrusXmlTest(packageScan= "com.citrus.testcases")
public void CitrusTest()
{
}
I am trying this code but citrus was not affecting the changed system properties
in the next test case it was executing the filenamepattern that was loaded the beginning is there any way to change system properties of citrus at runtime. Could any one please help on this.
Citrus will read the System property only once at startup. This is because this is a application wide environment setting that should not be changed after startup.
It seems that you want to load test cases based on some condition. I would rather use the TestNG test suite definitions where you can include and exclude tests based on packages, naming and other information given. You can read more information about that in the testng-documentation.
In addition to that I would suggest to put those tests into different test groups so you can easily execute those tests in different test runs.

I want to provide dynamic values to the paramaters of Citrus annotation(#CitrusXmlTest)

The values I want to provide dynamically is TestCase Name and Package name. How can I do this. If I am providing values through variable then it is giving the following error "The value for annotation attribute CitrusXmlTest.name must be a constant". Now I am giving like this
#CitrusXmlTest(name="Test",packageName="file:D://xitrus//myFirstTest.xml")
I want above statement to be
#CitrusXmlTest(name=variable name,packageName=variable name)
or in some other way to insert values dynamically please help me...
pom image 1,image 2,image 3
What you are trying to do is against Java annotation specification and is not possible due to these language limitations. Not sure what you are trying to achieve here.
In case you need to load test cases in a dynamic way you can use packageScan option in #CitrusXmlTest annotation:
#CitrusXmlTest(packageScan = "com.something.foo")
public void citrusPackageScanIT() {}
This will load and execute all XML test case definitions in package com.something.foo. The XML test definitions are free to use different test names then.
If you want to pass some dynamic data to your test case you should use a TestNG data provider (example given here: https://github.com/christophd/citrus-samples/tree/master/sample-dataprovider).

Spring Integration Test is Slow with Autowiring

I am trying to speed up the Integration tests in our environment. All our classes are autowired. In our applicationContext.xml file we have defined the following:
<context:annotation-config/>
<context:component-scan base-package="com.mycompany.framework"/>
<context:component-scan base-package="com.mycompany.service"/>
...additional directories
I have noticed that Spring is scanning all directories indicated above and then iterates over each bean and caches the properties of each one. (I went over the DEBUG messages from spring)
As a result, the following test takes about 14 seconds to run:
public class MyTest extends BaseSpringTest {
#Test
def void myTest(){
println "test"
}
}
Is there any way to lazy load the configuration? I tried adding default-lazy-init="true" but that didn't work.
Ideally, only the beans required for the test are instantiated.
thanks in advance.
Update: I should have stated this before, I do not want to have a context file for each test. I also do not think one context file for just the tests would work. (This test context file would end up including everything)
If you really want to speed up your application context, disable your <component-scan and performs the following routine before running any test
Resource resource = new ClassPathResource(<PUT_XML_PATH_RIGHT_HERE>); // source.xml, for instance
InputStream in = resource.getInputStream();
Document document = new SAXReader().read(in);
Element root = document.getRootElement();
/**
* remove component-scanning
*/
for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
Element element = (Element) i.next();
if(element.getNamespacePrefix().equals("context") && element.getName().equals("component-scan"))
root.remove(element);
}
in.close();
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true);
for (String source: new String[] {"com.mycompany.framework", "com.mycompany.service"}) {
for (BeanDefinition bd: scanner.findCandidateComponents(source)) {
root
.addElement("bean")
.addAttribute("class", bd.getBeanClassName());
}
}
//add attribute default-lazy-init = true
root.addAttribute("default-lazy-init","true");
/**
* creates a new xml file which will be used for testing
*/
XMLWriter output = new XMLWriter(new FileWriter(<SET_UP_DESTINATION_RIGHT_HERE>));
output.write(document);
output.close();
Besides that, enable <context:annotation-config/>
As you need to perform the routine above before running any test, you can create an abstract class where you can run the following
Set up a Java system property for testing environment as follows
-Doptimized-application-context=false
And
public abstract class Initializer {
#BeforeClass
public static void setUpOptimizedApplicationContextFile() {
if(System.getProperty("optimized-application-context").equals("false")) {
// do as shown above
// and
System.setProperty("optimized-application-context", "true");
}
}
}
Now, for each test class, just extends Initializer
One approach is to skip the auto detection completely and either load up a separate context (with the components required for the test) or redefine your beans at runtime (prior to the test running).
This thread discusses redefinition of beans and a custom test class for doing this:
Spring beans redefinition in unit test environment
This is the price you pay for auto-detection of components - it's slower. Even though your test only requires certain beans, your <context:component-scan> is much broader, and Spring will instantiate and initialise every bean it finds.
I suggest that you use a different beans file for your tests, one which only defines the beans necessary for the test itself, i.e. not using <context:component-scan>.
Probably what you need is to refactor your config to use less autowiring. My approach is almost always wire the beans by name, trying to be explicit with the design but, at the same time, not being too verbose either, using autowiring when is clear that you are using it in order to hide minor details.
Addendum:
If that is not enough and you are using junit, you may want to use a utility from the JUnit Addons project. The class DirectorySuiteBuilder dynamically builds up a test suite from a directory structure. So you can make something like
DirectorySuiteBuilder builder = new DirectorySuiteBuilder();
Test suite = builder.suite("project/tests");
Initializing the Spring context before this code, you can run all tests at once. However, if each test assume a "clean" Spring context, then you are probably lost.
In this kind of situation, you will need to find a balance.
On one hand, you would rightly want to run the tests in a shortest possible time to get the results quick. This is especially important when working in a team environment with continuous integration working.
On the other hand, you would also rightly want to keep the configuration of tests as simple as possible so the maintenance of test suite would not become too cumbersome to be useful.
But at the end of the day, you will need to find your own balance and make a decision.
I would recommend creating a few context configuration files for testing to group some tests so such a simple test would not take long time simply being configured by Spring, while keeping the number of configuration files to minimum you can manage.
Convention bean factory is designed to solve this problem and speeds up the whole process significantly, 3x or more.
Since none of the answers here solved this problem for me, I add my own experience.
My problem was that Spring, Hibernate and EhCache grouped up in the attempt of drowning my console with verbose DEBUG messages, resulting unreadable log and - far worse - unbearable low performance.
Configuring their log levels fixed all up:
Logger.getLogger("org.hibernate").setLevel(Level.INFO);
Logger.getLogger("net.sf.ehcache").setLevel(Level.INFO);
Logger.getLogger("org.springframework").setLevel(Level.INFO);

Unit test framework - TestNG using configurable value to define threadPoolSize

I'm digging little bit the TestNG framework.
I'm using annotations to configure thread values in my test case, example:
#Test(threadPoolSize = 2, invocationCount = 10)
public void testOne() {
//some code
}
The idea is config these values in a config file and this values should be passed to all tests.
So I need to change these values from a config entry or pass this value through unitTest constructor, but TestNG is only accepting constant values.
Any tips/ideas?
You need to use "IAnnotationTransformer" interface to make "invocationCount" and "threadPoolSize" parameter values configurable through a .properties file to override default values.
To address this issue, I've created a Sample Example. Please check this out https://github.com/pashtika/test-ng/tree/master/testng-annotation-configurable.

Categories

Resources