I have a class like the following;
class ClassA {
private static File myDir;
// myDir is created at some stage
private static String findFile(final String fileName) {
for (final String actualBackupFileName : myDir.list()) {
if (actualBackupFileName.startsWith(removeExtensionFrom(backupFile))) {
return actualBackupFileName;
}
}
}
}
So, basically, I want to test this class by mocking out the File class so that when list() is called on it it returns a list of strings I define in my test class.
I've got the following but its not working at the minute, there's probably something obvious I'm doing wrong - I'm new to JMockit - any help is much appreciated!
#Mocked("list") File myDir;
#Test
public void testClassA() {
final String[] files = {"file1-bla.txt"};
new NonStrictExpectations() {{
new File(anyString).list();
returns(files);
}};
String returnedFileName = Deencapsulation.invoke(ClassA.class, "findFile","file1.txt");
// assert returnedFileName is equal to "file1-bla.txt"
}
When running the above test I get a NullPointerException for the myDir field in ClassA - so it looks like its not getting mocked properly?
You can use the setField method from the Deencapsulation class. Note example below:
Deencapsulation.setField(ClassA, "File", your_desired_value);
JMockit (or any other mocking tool) does not mock fields or variables, it mocks types (classes, interfaces, etc.) Where the instances of those types get stored inside the code under test is not relevant.
Example test for ClassA:
#Test
public void testClassA(#Mocked File myDir)
{
new Expectations() {{ myDir.list(); result = "file1-bla.txt"; }};
String returnedFileName = new ClassA().publicMethodThatCallsFindFile("file1.txt");
assertEquals("file1-bla.txt", returnedFileName);
}
The above should work. Note that testing private methods directly (or accessing private fields) is considered bad practice, so I avoided it here. Also, it's best to avoid mocking the File class. Instead, test only your public methods, and use actual files instead of mocking the filesystem.
try out this:
new Expectations {{
invoke(File.class, "list", null, null);
returns(files);
}}
Related
In my Junit test, I'm doing the following in my Junit test :
#Before
public void setUp() throws Exception {
reportQueryParams = ReportQueryParams.builder()
.id("07")
.build();
}
#Test
public void tabSerializerTest() {
MetricsSerializer mockMonth = mock(MetricsSerializer.class);
when(mockMonth.getCurrentMonth()).thenReturn("July");
String tabSeparated = mockMonth.serializeMetrics(reportQueryParams);
String expected = new StringBuilder().append("074")
.append("\t")
.append("July")
.toString();
assertEquals(expected, tabSeparated);
}
The function which I am testing:
public String serializeMetrics(final ReportQueryParams reportQueryParams) {
stringJoiner = new StringJoiner("\t");
addValueFromString(reportQueryParams.getId());
addValueFromString(getCurrentMonth());
return stringJoiner.toString();
}
public String getCurrentMonth() {
DateFormat monthFormat = new SimpleDateFormat("MMMMM");
return monthFormat.format(new Date());
}
private void addValueFromString(final String value) {
stringJoiner.add(value);
}
My ReportQueryParams class:
public class ReportQueryParams {
private String id;
}
I am getting "null" in the actual data returned and hence the test is failing. How can I fix this?
Don't mock the object you test.What you have written is "create a mock object that returns July for current month". But this mock object doesn't have real behaviour and the other methods return null.
When you test a class you mock the objects required by the class (in order to insulate behaviour) and not the actual class. Here you can create a new MetricsSerializer (by using new :) and call it's method serializeMethod and compare against the current date (instead of July).
The way you have written the class might not be the best testable way though ;)
Your problem is that you are mocking the class, then testing the mock object, rather than testing a "real" object. I can think of two possible solutions.
Use a Mockito Spy instead of a mock. This is like a mock, but it's a real object, and the methods all have their normal behaviour, instead of "no behaviour" by default. You can stub the getCurrentMonth method of your spy, to make it return what you want.
Since the real cause of your problem is the call to new Date(), you could use a time helper, instead of calling new Date() directly in your getCurrentMonth() method. I have described this technique in detail in my answer to this question
I am new to writing tests in java, and seem to be unable to test if a method of a class is called.
I am sending metrics to datadog, and want to test in the code if a function of another class was called.
It says I need to mock first, but I couldn't get it to work.
MetricRecorder.java
import com.timgroup.statsd.StatsDClient;
import com.timgroup.statsd.NonBlockingStatsDClient;
import com.google.common.base.Preconditions;
public class MetricRecorder {
private final String namespace;
private final static StatsDClient metrics = new NonBlockingStatsDClient(
"my.prefix",
"localhost",
8125,
new String[] {"tag:value"}
);
public MetricRecorder(String namespace) {
Preconditions.checkNotNull(namespace);
this.namespace = namespace;
}
public void inc(String metricName) {
this.inc(metricName, 1);
}
public void inc(final String metricName, final long value) {
Preconditions.checkNotNull(metricName);
try {
metrics.recordHistogramValue(MetricRecorder.name(namespace, metricName), value);
} catch (Exception e) {
logger.warn("Unable to record metric {} due to :", metricName, e);
}
}
...
}
MetricRecorderTest.java
public class MetricsRecorderTest {
#Test
public void metricsRecorderTest() {
MetricRecorder recorder = new MetricRecorder("dev");
recorder.inc("foo", 1);
verify(recorder.metrics, times(1)).recordHistogramValue(eq("dev.foo"), 1);
}
}
When I run the test I get this => org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type NonBlockingStatsDClient and is not a mock!
Any idea of how I should be testing if recordHistogramValue was called, and if so with what arguments?
Since it looks like StatsDClient is an interface of some kind, it would make your testing effort easier to simply inject this dependency into your object. Even if you're not using an IoC container like Spring or Guice, you can still somewhat control this simply by passing an instance of it in through the constructor.
public MetricRecorder(String namespace, StatsDClient client) {
Preconditions.checkNotNull(namespace);
Preconditions.checkNotNull(client);
this.namespace = namespace;
this.client = client;
}
This will make your testing simpler since all you realistically need to do is mock the object passed in during test.
Right now, the reason it's failing is because you're newing up the instance, and Mockito (in this current configuration) isn't equipped to mock the newed instance. In all honesty, this set up will make testing simpler to conduct, and you should only need your client configured in one area.
#RunWith(MockitoJUnitRunner.class)
public class MetricsRecorderTest {
#Test
public void metricsRecorderTest() {
StatsDClient dClientMock = Mockito.mock(StatsDClient.class);
MetricRecorder recorder = new MetricRecorder("dev", dClientMock);
recorder.inc("foo", 1);
verify(recorder.metrics).recordHistogramValue(eq("dev.foo"), 1);
}
}
You are getting things wrong here. You don't use a mocking framework to test your "class under test".
You use the mocking framework to create mocked objects; which you then pass to your "class under test" within a test case. Then your "code under test" calls methods on the mocked object; and by controlling returned values (or by verifying what happens to your mock); that is how you write your testcases.
So, your testcase for a MetricRecorder doesn't mock a MetricRecorder; it should mock the StatsDClient class; and as Makoto suggests; use dependency injection to put an object of that class into MetricRecorder.
Besides: basically writing "test-able" code is something that needs to be practiced. I wholeheartedly recommend you to watch these videos if you are serious about getting in this business. All of them; really (worth each second!).
I have following code preparing mocks to test my service using Cassandra (I need to mock com.datastax.driver.core.ColumnDefinitions.Definition) :
#RunWith(PowerMockRunner.class)
public class TestMyClass{
private MyClass target;
#Before
public void setUp() throws Exception {
ColumnDefinitions mockColumnDefinitions=Mockito.mock(ColumnDefinitions.class);
Mockito.when(mockRow.getColumnDefinitions()).thenReturn(mockColumnDefinitions);
target= new MyClass();
Definition mockDef = Mockito.mock(Definition.class);
List<Definition> defList = new ArrayList<Definition>();
defList.add(mockDef);
Iterator mockIterator = Mockito.mock(Iterator.class);
Mockito.when(mockColumnDefinitions.iterator()).thenReturn(mockIterator);
Mockito.when(mockIterator.hasNext()).thenReturn(true, false);
Mockito.when(mockIterator.next()).thenReturn(mockDef);
Mockito.when(mockDef.getName()).thenReturn(NAME);
}
#Test
public void testMyMethod() throws Exception {
target.MyMethod();
}
}
Test execution goes fine this place, and I have this type of code in different places, so it should work.
Inside the service I am testing I have following code:
ColumnDefinitions colDef = row.getColumnDefinitions();
Iterator<Definition> defIterator = colDef.iterator();
while (defIterator.hasNext()) {
Definition def = defIterator.next();
String columnName = def.getName();
}
When I debug this code, I see, that both colDef and defIterator are mocked successfully. I see something like that in debug variables area:
Mock for Iterator, hashCode: 430126690
But after defIterator.next() invocation I see that though def is an object and not null, it doesn't show hashcode like for Iterator, instead I see this:
com.sun.jdi.InvocationException occurred invoking method.
And after invoking this string:
String columnName = def.getName();
I immediately get NullPointerException like if def is null.
What am I doing wrong?
Thanks.
EDIT 1 ________________________________________________________________________
I also tried to use PowerMockito with the same methods instead, the result is the same.
EDIT 2 ________________________________________________________________________
I added the whole test method code.
It is been a while since this question was created. I have faced this same problem few days ago and I have solved it in the following manner (I hope my proposed solution helps someone in the future):
First of all, I want to clarify that ColumnDefinition.Definition class is a public static nested class that has four private final fields and only has one constructor: Definition (String keyspace, String table, String name and DataType type) (for more details please refer to the ColumnDefinitions.Definition javadoc and ColumnDefinitions source code). Therefore this nested class could not be mocked by Mockito nor Powermock because of its final fields.
SOLUTION:
I had to create a real object, not a mocked one of the class ColumnDefinition.Definition using reflection, so you can initialise the mockDef object as follows:
Constructor<Definition> constructor = (Constructor<Definition>) Definition.class.getDeclaredConstructors()[0]; // as Definition only has one constructor, 0 will be passed as index
constructor.setAccessible(true);
Definition mockDef = constructor.newInstance("keyspace", "table", "name", null);
replacing this line of code in your snippet:
Definition mockDef = Mockito.mock(Definition.class);
Then the NullPointerException will never be thrown again when executing this line of code:
String columnName = def.getName();
I have the following code, where each url in listOne is tested with the method testItem:
#Parameters(name="{0}")
public static Collection<Object[]> data() throws Exception {
final Set<String> listOne = getListOne();
final Collection<Object[]> data = new ArrayList<>();
for (final String url : listOne) {
data.add(new Object[] { url });
}
return data;
}
#Test
public void testItem() {
driverOne.makeDecision(urlToTest);
assertTrue(driverOne.success(urlToTest);
}
What if I now wanted to add a second list, listTwo, and run a test method defined as follows on JUST the items of listTwo (but not listOne?)
#Test
public void testItemAlternate() {
driverTwo.makeDecision(urlToTest);
assertTrue(driverTwo.success(urlToTest));
}
That is, I want driverOne to make the decision for all URLs in listOne, and I want driverTwo to make the decision for all URLs in listTwo. What is the best way to translate this to code? Thanks.
Cited from: https://github.com/junit-team/junit/wiki/Parameterized-tests
The custom runner Parameterized implements parameterized tests. When running a parameterized test class, instances are created for the cross-product of the test methods and the test data elements.
Thus, I assume No, that's not possible.
If you want to do such a thing I guess that you either
(1) will need to construct two test classes one for each test to be executed with the first collection and one for each test to be executed with the second collection or
(2) will need to use another mechanism besides the #Parameters annotation, maybe hand-crafted.
You could include some test set identifier in your test set data itself, and then use the org.junit.Assume class to help:
#Test
public void testItem() {
org.junit.Assume.assumeTrue(testSetId.equals("TEST_SET_1"));
driverOne.makeDecision(urlToTest);
assertTrue(driverOne.success(urlToTest);
}
#Test
public void testItemAlternate() {
org.junit.Assume.assumeTrue(testSetId.equals("TEST_SET_2"));
driverTwo.makeDecision(urlToTest);
assertTrue(driverTwo.success(urlToTest));
}
As a completely different answer, there exists junit-dataprovider
I inherited an application which uses a java properties file to define configuration parameters such as database name.
There is a class called MyAppProps that looks like this:
public class MyAppProps {
protected static final String PROP_FILENAME = "myapp.properties";
protected static Properties myAppProps = null;
public static final String DATABASE_NAME = "database_name";
public static final String DATABASE_USER = "database_user";
// etc...
protected static void init() throws MyAppException {
try {
Classloader loader = MyAppException.class.getClassLoader();
InputStream is = loader.getResourceAsStream(PROP_FILENAME);
myAppProps = new Properties();
myAppProps.load(is);
} catch (Exception e) {
threw new MyAppException(e.getMessage());
}
}
protected static String getProperty(String name) throws MyAppException {
if (props==null) {
throw new MyAppException("Properties was not initialized properly.");
}
return props.getProperty(name);
}
}
Other classes which need to get property values contain code such as:
String dbname = MyAppProps.getProperty(MyAppProps.DATABASE_NAME);
Of course, before the first call to MyAppProps.getProperty, MyAppProps needs to be initialized like this:
MyAppProps.init();
I don't like the fact that init() needs to be called. Shouldn't the initialization take place in a static initialization block or in a private constructor?
Besides for that, something else seems wrong with the code, and I can't quite put my finger on it. Are properties instances typically wrapped in a customized class? Is there anything else here that is wrong?
If I make my own wrapper class like this; I always prefer to make strongly typed getters for the values, instead of exposing all the inner workings through the static final variables.
private static final String DATABASE_NAME = "database_name"
private static final String DATABASE_USER = "database_user"
public String getDatabaseName(){
return getProperty(MyAppProps.DATABASE_NAME);
}
public String getDatabaseUser(){
return getProperty(MyAppProps.DATABASE_USER);
}
A static initializer looks like this;
static {
init();
}
This being said, I will readily say that I am no big fan of static initializers.
You may consider looking into dependency injection (DI) frameworks like spring or guice, these will let you inject the appropriate value directly into the places you need to use them, instead of going through the indirection of the additional class. A lot of people find that using these frameworks reduces focus on this kind of plumbing code - but only after you've finished the learning curve of the framework. (DI frameworks are quick to learn but take quite some time to master, so this may be a bigger hammer than you really want)
Reasons to use static initializer:
Can't forget to call it
Reasons to use an init() function:
You can pass parameters to it
Easier to handle errors
I've created property wrappers in the past to good effect. For a class like the example, the important thing to ensure is that the properties are truly global, i.e. a singleton really makes sense. With that in mind a custom property class can have type-safe getters. You can also do cool things like variable expansion in your custom getters, e.g.:
myapp.data.path=${myapp.home}/data
Furthermore, in your initializer, you can take advantage of property file overloading:
Load in "myapp.properties" from the classpath
Load in "myapp.user.properties" from the current directory using the Properties override constructor
Finally, load System.getProperties() as a final override
The "user" properties file doesn't go in version control, which is nice. It avoids the problem of people customizing the properties file and accidentally checking it in with hard-coded paths, etc.
Good times.
You can use either, a static block or a constructor. The only advice I have is to use ResourceBundle, instead. That might better suit your requirement. For more please follow the link below.
Edit:
ResourceBundles vs Properties
The problem with static methods and classes is that you can't override them for test doubles. That makes unit testing much harder. I have all variables declared final and initialized in the constructor. Whatever is needed is passed in as parameters to the constructor (dependency injection). That way you can substitute test doubles for some of the parameters during unit tests.
For example:
public class MyAppProps {
protected static final String PROP_FILENAME = "myapp.properties";
protected Properties props = null;
public String DATABASE_NAME = "database_name";
public String DATABASE_USER = "database_user";
// etc...
public MyAppProps(InputStream is) throws MyAppException {
try {
props = new Properties();
props.load(is);
} catch (Exception e) {
threw new MyAppException(e.getMessage());
}
}
public String getProperty(String name) {
return props.getProperty(name);
}
// Need this function static so
// client objects can load the
// file before an instance of this class is created.
public static String getFileName() {
return PROP_FILENAME;
}
}
Now, call it from production code like this:
String fileName = MyAppProps.getFileName();
Classloader loader = MyAppException.class.getClassLoader();
InputStream is = loader.getResourceAsStream(fileName);
MyAppProps p = new MyAppProps(is);
The dependency injection is when you include the input stream in the constructor parameters. While this is slightly more of a pain than just using the static class / Singleton, things go from impossible to simple when doing unit tests.
For unit testing, it might go something like:
#Test
public void testStuff() {
// Setup
InputStringTestDouble isTD = new InputStreamTestDouble();
MyAppProps instance = new MyAppProps(isTD);
// Exercise
int actualNum = instance.getProperty("foo");
// Verify
int expectedNum = 42;
assertEquals("MyAppProps didn't get the right number!", expectedNum, actualNum);
}
The dependency injection made it really easy to substitute a test double for the input stream. Now, just load whatever stuff you want into the test double before giving it to the MyAppProps constructor. This way you can test how the properties are loaded very easily.