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
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
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.
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
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
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.