test case not covering in cobertura - java

public class MyUtil {
public static Properties loadProperties() throws Exception {
Properties prop = new Properties();
InputStream inputStream = MyUtil.class.getClassLoader().getResourceAsStream(PROPERTY_FILENAME);
if (inputStream != null) {
prop.load(inputStream);
}
return prop;
}
}
I have written test case for the above method, when I ran as test case in eclipse it's passing and when I debug loadProperties() is not getting called and cobertura report is showing as uncovered code.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ MyUtil.class, Properties.class })
#Test
public void testLoadProperties() throws Exception{
String fileName = "application.properties";
Properties mockProps = PowerMockito.mock(Properties.class);
PowerMockito.mockStatic(Properties.class);
PowerMockito.whenNew(Properties.class).withNoArguments().thenReturn(mockProps);
InputStream mockInputStream = Mockito.mock(InputStream.class);
PowerMockito.mockStatic(MyUtil.class);
ClassLoader mockClassLoader = Mockito.mock(ClassLoader.class);
PowerMockito.when(MyUtil.class.getClassLoader()).thenReturn(mockClassLoader);
PowerMockito.when(mockClassLoader.getResourceAsStream(fileName)).thenReturn(mockInputStream);
PowerMockito.doNothing().when(mockProps).load((InputStream)Mockito.any());
MyUtil.loadProperties();
//assertNotNull("Not Null", MyUtil.loadProperties()); //assert failing
}
what should I change to make sure that my code actually covers in code coverage?

It's old well-known issue that PowerMock breaks code coverage tools:
https://github.com/cobertura/cobertura/issues/94
In current moment, there is only one way to get code coverage JaCoCo Offline instrumenting
https://github.com/powermock/powermock/wiki/Code-coverage-with-JaCoCo

Related

Mock files, but generate real files

I use the SpringBoot mail component to generate eml files. When I use mockito to simulate, Why would a real file be generated?
This is my demo
#Resource
private JavaMailSender javaMailSender;
public File createEml(String filename) throws IOException, MessagingException {
File file = new File(filename);
try(FileOutputStream fos = new FileOutputStream(file)) {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
mimeMessage.writeTo(fos);
}
return file;
}
}
test
#InjectMocks
private EmailManager emailManager = new EmailManager();
#Mock
private JavaMailSender javaMailSender;
#BeforeEach
private void setUp() {
MockitoAnnotations.openMocks(this);
}
#Test
void testCreateEml() throws MessagingException, IOException {
MimeMessage mimeMessage = Mockito.mock(MimeMessage.class);
Mockito.doNothing().when(mimeMessage).writeTo(Mockito.any(FileOutputStream.class));
Mockito.when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage);
emailManager.createEml("test.eml");
}
Because you don’t create a mock of EmailManager
Usually #InjectMocks annotation is use on the class that you’re about to test (EmailManager in this case)
This is a real code that you don’t want to mock (there is no point to write a test that tests a mock) - you always want to test the real code and mocks is just an auxiliary tool to “mimic” the behavior of dependencies
So in the EmailManager the method createEml is real - and file creation is just what it does - you’ve posted the source code of it. This code gets executed during the test. That’s it.
So if you want to create a test that doesn’t create any real file you should refactor the file creation part in a way that it will support file creation of “virtual” files in memory. After all not any arbitrarily-written pieces of code can are automatically unit-testable, you have to design the code with “unit-test ability” in mind

robolectric doesn't use ~config-package namespace attribute

I want to add robolectric to an existing and live android-dagger project
The problem is that the package name in the AndroidManifest is not aligned with the R file physical path.
robolectric searches for the R file according to the manifest "package_name" attribute.
I thought to use #Config over my robolectric test
#Config(manifest = " --my---path/AndroidManifest.xml",
sdk = 21,
packageName = "com.google.andorid.apps.ridematch",
application = TestApplication.class)
but apparently the "packageName" annotation is not effective.
I wanted to debug this in the robolectric open source,
but wasn't sure where was the problematic code.
It was a chance for me to first contribute to a github open-source project
my tries:
try 1)
I thought the bug is in code:
#Test
public void shouldAssignThePackageNameFromTheManifest() throws Exception {
AndroidManifest appManifest = newConfigWith("com.wacka.wa", "");
Application application = defaultTestLifecycle.createApplication(null, appManifest, null);
shadowOf(application).bind(appManifest, null);
assertThat(application.getPackageName()).isEqualTo("com.wacka.wa");
assertThat(application).isExactlyInstanceOf(Application.class);
}
so I wrote this code:
#Test
public void shouldAssignThePackageNameFromConfigWhenHaveConfigAndManifest() throws Exception {
AndroidManifest appManifest = newConfigWith("com.wacka.wa", "");
Properties properties = new Properties();
properties.put("packageName", "com.robolectric.MyTestClass");
properties.put("application", "com.robolectric.TestTestApplication");
// properties.put("application", "FakeApp");
Config config = Config.Implementation.fromProperties(properties);
Application application = defaultTestLifecycle.createApplication(null, appManifest, config);
shadowOf(application).bind(appManifest, null);
assertThat(application.getPackageName()).isEqualTo("com.robolectric.MyTestClass");
assertThat(application).isExactlyInstanceOf(TestTestApplication.class);
}
In "bind" i made non null config-package name override appManifest package name.
but I couldn't find who calls "defaultTestLifecycle.createApplication"
try 2)
I started looking at this class and its tests:
#Override
protected AndroidManifest getAppManifest(Config config) {
I saw this test:
#Ignore
#Config(constants = BuildConfig.class, packageName = "fake.package.name")
public static class PackageNameTest {
#Test
public void withoutAnnotation() throws Exception {
}
}
and I have added mine:
#Ignore
#Config(constants = BuildConfig.class, packageName = "fake.package2.name", manifest = "//java/com/google/android/apps/ridematch/environments/debug:AndroidManifest.xml")
public static class PackageNameConfigAndManifestTest {
#Test
public void withoutAnnotation() throws Exception {
}
}
but the test passed, so the bug is not there.

Junit testsuite in Jmeter

Does Jmeter supports Junit testsuite?
This question trouble me for several days, the test cases all working well no matter a style of junit 3 or 4. But the testsuite is anyway dumb.
Any suggestions?
My code below:
public class LoginLogout extends TestCase {
private static Logger log = Logger.getLogger(LoginLogout.class);
public static Test suite() {
try{
log.info("test suite start!");
TestSuite suite = new TestSuite(LoginLogout.class.getName());
//$JUnit-BEGIN$
suite.addTestSuite(Login.class);
suite.addTestSuite(Logout.class);
return new TestSetup(suite) {
protected void setUp(){
log.info("test suite setup!");
}
protected void tearDown(){
log.info("test suite finished!");
}
};
}catch(Exception e){
log.error(e.getMessage());
}
return null;
}
}
public class Login extends TestCase {
private static Logger log = Logger.getLogger(Login.class);
#Test
public void testLogin() throws Exception {
log.info("login start!");
log.info("login end!");
}
}
public class Logout extends TestCase {
private static Logger log = Logger.getLogger(Logout.class);
#Test
public void testLogout() throws Exception {
log.info("logout start!");
log.info("logout end!");
}
}
You can go to "Download Apache JMeter" page on http://jmeter.apache.org/ , and download the "apache-jmeter-2.8_src.zip" (or whatever the current version is).
After unzipping it, under apache-jmeter-2.8_src\apache-jmeter-2.8\src\junit\test directory, you can find the following java files (as for jmeter version 2.8):
For JUnit4:
AfterAnnotatedTest.java
BeforeAnnotatedTest.java
DummyAnnotatedTest.java
Junit4AnnotationsTest.java
For JUnit3:
RerunTest.java
SetupTestError.java
SetupTestFail.java
TearDownTestFail.java
You can see them shown up at the Classname dropdown menu on JUnit Request of JMeter (Test Plan --> Thread Group --> JUnit Request).
Those JUnit test cases are provided by JMeter by default, so I assume that a simple copy-and-paste of their code and work from there should work; however, so far, I am not able to see my test cases shown up at the Classname dropdown menu.
Here are other useful links I have found; however, none of them solves the current problem I am encountering:
Running Selenium scripts from Jmeter
http://jmeter.apache.org/usermanual/junitsampler_tutorial.pdf
JUnit test classes not showing up in JMeter
For JUnit4 the Suite would be:
#RunWith(Suite.class)
#SuiteClasses({Login.class, Logout.class})
public class LoginLogout {
private static Logger log = Logger.getLogger(LoginLogout.class.getName());
}
And the TestClass is:
public class Login {
private static Logger log = Logger.getLogger(Login.class.getName());
#Test
public void testLogin() throws Exception {
log.info("login start!");
log.info("login end!");
}
}
Worked fine for me

JUnit : When do I declare a TemporaryFolder object?

I am trying to test a method that copies a source file to a dest file using JUnit's TemporaryFolder. I get a Java IOException when I try run this test however. Does it matter where I make the declaration for the folder? (My test class has several different tests in it). And if so, what is the proper way to do it? I ask because I currently have several unit tests above this code, then I try to set up the testing for the file copying. Maybe the #Rule-#Before-#Test block needs to be in its own class? Here is the snippet where I have coded the test:
...other tests...then:
#Rule
public static TemporaryFolder tmp = new TemporaryFolder();
private File f1, f2;
#Before
public void createTestData() throws IOException {
f1 = tmp.newFile("src.txt");
f2 = tmp.newFile("dest.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f1));
out.write("This should generate some \n" +
"test data that will be used in \n" +
"the following method.");
out.close();
}
#Test
public void copyFileTest() {
out.println("file 1 length: " + f1.length());
try {
copyFile(f1, f2);
} catch (IOException e) {
e.getMessage();
e.printStackTrace();
}
if (f1.length() != f2.length())
fail();
else if (!f1.equals(f2))
fail();
assertSame(f1, f2);
}
When I run this test class, all 11 of my tests now fail (which previously passed) and I get java.io.IOException: No such file or directory.
So looking at the JUnit Javadoc, I have found out that any declaration under #Rule must be public, and not static. So I took out the static and just have:
#Rule
public TemporaryFolder tmp = new TemporaryFolder();
I still do not know for sure if it matters where this declaration is made when you have other unit tests in your class that do not use the #Rule declaration, but this did allow me to run through my tests successfully.
If you really want to declare TemporaryFolder as static, you can use #ClassRule which is used to annotate static fields that contains Rule.
#ClassRule
public static TemporaryFolder tmp = new TemporaryFolder();
Reference: http://junit-team.github.io/junit/javadoc/4.10/org/junit/ClassRule.html

Run all tests in a source tree, not a package

My unit tests are in a separate directory tree from my integration tests, but with the same package structure. My integration tests need external resources (e.g. a server) to be available, but my unit tests are properly independent of each other and the environment.
In IntelliJ-IDEA (v7) I have defined a JUnit Run/Debug Configuration to run all the tests in the top-level package, and this of course picks up my integration tests which fail.
I want to define a run-junit configuration that runs all my unit tests. Any ideas?
The answer is to create a test suite that contains only those tests underneath the unit test folder and run that instead. There is a junit-addon which does just this called DirectorySuiteBuilder but I only found this after I had pretty much re-invented the wheel.
And it's already been asked here!
import junit.framework.JUnit4TestAdapter;
import junit.framework.TestSuite;
import java.io.File;
import java.io.IOException;
public class DirectoryTestSuite {
static final String rootPath = "proj\\src\\test\\java\\";
static final ClassLoader classLoader = DirectoryTestSuite.class.getClassLoader();
public static TestSuite suite() throws IOException, ClassNotFoundException {
final TestSuite testSuite = new TestSuite();
findTests(testSuite, new File(rootPath));
return testSuite;
}
private static void findTests(final TestSuite testSuite, final File folder) throws IOException, ClassNotFoundException {
for (final String fileName : folder.list()) {
final File file = new File( folder.getPath() + "/" +fileName);
if (file.isDirectory()) {
findTests(testSuite, file);
} else if (isTest(file)) {
addTest(testSuite, file);
}
}
}
private static boolean isTest(final File f) {
return f.isFile() && f.getName().endsWith("Test.java");
}
private static void addTest(final TestSuite testSuite, final File f) throws ClassNotFoundException {
final String className = makeClassName(f);
final Class testClass = makeClass(className);
testSuite.addTest(new JUnit4TestAdapter(testClass));
}
private static Class makeClass(final String className) throws ClassNotFoundException {
return (classLoader.loadClass(className));
}
private static String makeClassName(final File f) {
return f.getPath().replace(rootPath, "").replace("\\", ".").replace(".java", "");
}
}
IntelliJ IDEA CE 10.5 has a (new?) option to run all tests inside a configured directory:
Unfortunately there's no way to separate the output from the IntelliJ compile other than by classes and test classes within a single module (it's the classes that test runner is looking at).
So when I have integration tests I simply use a second module specific to these tests to get round this problem, specifying output directories as necessary for each module.

Categories

Resources