JUnit method dependency - java

I would like to ask a simple question about the best practice of testing methods. Lets say I have a class like this,
public static class MyClass {
private int num;
public MyClass(int num) {
this.num = add(num);
}
public int getNum() {
return num;
}
private int add(int num) {
return num + 1;
}
}
Is it better to write a single test method like this
Assert.assertEquals(3, new MyClass(2).getNum());
or to stub the add method and write a test method for constructor to assert inner num value and getNum seperately? I know it is a simple class and no need for such complications for this one but I wanted to point out the issue with a simple example. It would be appreciated if you explain your answer, thanks in advance.

Let's say your test fails.
Will you be able to see right away where your error is located? No. You'd have to check both methods manually.
Let's say your test succeeds.
Can you be sure both of your methods work correctly? No. They both might do something not intended just returning the checked for value by accident
So my clear advice on this: One test per method.

I think, you should test both ways - by stubbing private methods and without stubbing private methods.
Isolation of unit test methods is important but execution of full logical path is equally important too so test both ways and name your test methods accordingly.

Related

How to assert the number of assertions (or some other way to enforce that all members have been tested in an assertion)?

In a certain unit test for my class, I want to assert that an assertion has been written for all member fields. That is, given
public class Foo {
int a;
int b;
String c;
}
I want to do something like
#Test
public void testFieldsAgainstExternalModel(Foo model, Bar externalModel) {
assertEquals(model.a, externalModel.getA());
assertEquals(model.b, externalModel.getSomethingNamedDifferently());
assertEquals(model.c, externalModel.getC().toString());
assertNumberOfAssertionsInThisTest(3); // <-- How do I do this?
}
Of course, counting the number of assertions doesn't ensure that they had anything to do with each field having an assertion. But, I'm just trying to write a test that fails if a developer adds a field to Foo and forgets to update this test.
Naivest approach: The simplest thing I can think of is to use reflection to assert the number of fields Foo has, e.g. assertEquals(3, Foo.getDeclaredFields().count()). But, I can easily see a programmer bumping up the number without actually adding an assertion.
Still a naive approach, but acceptable: I think if I can at least count the number of assertions, it would sufficiently guide programmers toward the intended need.
More exact approaches: Of course it seems to best approach is to actual keep a table of which fields have appeared in the assertion (e.g. through a wrapper method like assertEqualsWithCounters), but in reality my situation's a little more complicated. For example, my model is actually a generated class (#AutoMatter) and I'll be using getters on both sides of the assertion, so it'll be hard to infer truly which field has been "touched" by an assertion. That's why just counting assertions and remaining agnostic to actual types and counts, would be easiest for me.
But, I'm just trying to write a test that fails if a developer adds a
field to Foo and forgets to update this test.
My company uses a mapping framework to map beans from the db, fields are one to one with the database, to a model bean we return to the client that we can modify as needed. I believe this is a common use case and essentially what you are trying to get at. You should be less concerned with testing changes to Foo, and more concerned with ensuring nothing breaks with the mapping from Foo to Bar.
Class BeanDb{
private int a;
private int b;
...
}
Class Bean{
private int a;
private int b;
private String somethingElse;
...
}
Then we have have a proivder test that uses isEqualToComparingFieldByFieldRecursively to compare the two beans.
private Bean bean = new Bean();
private Bean beanDb = new BeanDb();
private BeanProvider provider = new BeanProvider();
#Before
public void setup(){
bean.setA(1);
bean.setB(2);
beanDb.setA(1);
beanDb.setB(2);
}
#Test
public void prepareForDatabase(){
BeanDb db = provider.prepareForDatabase(bean);
assertThat(beanDb).isEqualToComparingFieldByFieldRecursively(db);
}
#Test
public void populateFromDatabase(){
Bean model = provider.populateFromDatabase(beanDb);
assertThat(model).isEqualToComparingFieldByFieldRecursively(bean);
}
This actually catches a lot of bugs. If something changes in the model bean / db bean the test will break in our continuous integrations suite. The caveat here is that isEqualToComparingFieldByFieldRecursively will not catch newly added fields.
When I review code / pull requests and BeanDb or the provider has been updated I ask, "Did you update the provider test?"
I think you may need to use PowerMockito as Mockito does not support mocking static methods.
I haven't tested the code below - but my idea would be to do the following:
#RunWith(PowerMockRunner.class)
public class Tester {
public class Foo {
int a = 5;
int b = 6;
String c = "7";
}
class Bar {
public int getA() {
return 5;
}
public int getSomethingNamedDifferently() {
return 6;
}
public Integer getC() {
return 7;
}
}
#Test
public void testFieldsAgainstExternalModel() {
testFieldsAgainstExternalModel(new Foo(), new Bar());
}
public void testFieldsAgainstExternalModel(Foo model, Bar externalModel) {
Assert spiedAssert = PowerMockito.spy(Assert.class);
spiedAssert.assertEquals(model.a, externalModel.getA());
spiedAssert.assertEquals(model.b, externalModel.getSomethingNamedDifferently());
spiedAssert.assertEquals(model.c, externalModel.getC().toString());
PowerMockito.verify(spiedAssert, times(3)).assertEquals(any(), any());
}
}
I think that the answer to
assertNumberOfAssertionsInThisTest(3); // <-- How do I do this?
is: you do not do that. This test is close to useless.
If there are only 3 fields, you can see with your eyes that you are checking those three fields. You are probably thinking about 15 fields in that class, but then:
assertEquals(model.a, externalModel.getA());
assertEquals(model.b, externalModel.getSomethingNamedDifferently());
assertEquals(model.c, externalModel.getC().toString());
assertEquals(model.c, externalModel.getC().toString());
assertEquals(model.d, externalModel.getD().toString());
...
assertEquals(model.o, externalModel.getO().toString());
assertNumberOfAssertionsInThisTest(15);
would not help you. Guess what: when pulling together my faked example, I omitted property 14 (model.n), but instead I had a copy/paste error and checked model.c two times, leading to an overall count of 15.
Therefore I agree with user Phil, just suggesting yet another approach, like this:
ensure that the bean classes have reasonable equals() (and maybe hashCode() methods). Either by using Lombok, or by having a base bean class that makes use of an EqualsBuilder (we actually do the later in our projects)
then have test code either use a faked bean and simply compare if that faked bean is equal to the bean that your production code created from a (maybe faked) external model object.

Java variable not assigned in JUnit Test Class

I found something strange in my project. I create a test class using JUnit to test my service layer. The service layer itself is not my question. My problem is, I don't know why after I assigned a value to an int variable in my first test method, and then when I try to use that value in the second test method, the variable value is 0
Executed in order because I use #FixMethodOrder(MethodSorters.NAME_ASCENDING)
int id;
#Test
public void firstMethodToTest() {
id = 10;
System.out.println(id); // here printed correctly 10
}
#Test
public void secondMethodToTest() {
System.out.println(id); // here printed 0
}
I also try to change int to Integer but it returns null not 0 anymore.
I wonder if in JUnit Test class like this, Java variable acts differently.
Thanks.
Thanks to #Ivan for giving me a clue to the answer
For each test method (the method annotated with #Test), a new instance of YourTestClass will be created. This is the behavior of Junit.
So, the point is if you want to use a class member for all test methods, just declare the variable as static. In my case: static int id;

Unit-test wrapper methods when base method is private [duplicate]

This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 6 years ago.
I read this answer about unit-test a wrapper method. In following code:
public static Object methodA(Object arg) {
if (arg == null) {
return null;
} else {
return methodB();
}
}
It looks reasonable that I don't need to test all functionality in methodB(), just test 2 cases where arg is null and not because methodB() should be tested already.
However, if methodB() is private method, I should test all functionality that methodB() will provide because according to another answer, private methods are implementation details.
The problem is, if I have 2 methods methodA1() and methodA2() and they all call methodB() like this:
public static MyObject methodA1(int x) {
MyObject obj = new MyObject();
obj.setX(x);
return methodB(obj);
}
public static MyObject methodA2(int y) {
MyObject obj = new MyObject();
obj.setY(y);
return methodB(obj);
}
private static MyObject methodB(MyObject obj) {
// doSomething with obj
return obj;
}
Should I test methodA1() and methodA2() separately? Or I can just test the private method methodB() because methodA1() and methodA2() are just wrapper methods of methodB(), so if methodB() is correctly tested, I won't need to test methodA1() and methodA2() at all.
EDIT:
I wrote separate tests for public methods at first. But the problem is, if there are many variations of the methodA, and some of the functionalities / requirements are shared in some of them, then the code of the test cases will be duplicated. That's why I wonder if I should test private method methodB().
The real problem I met is I have requirement to add a record in database, and there are many different APIs I should provide. For example, I should provide:
MyObject addMale(String name, String job); // fill sex with "Male"
MyObject addStudent(String name, String sex); // fill job with "Student"
And all of them checks the parameter is valid or not, fill the field that is not specified and call the private method to actually insert the record into the database, which is so called methodB().
There are many APIs like this, so if I can only test methodB() with all fields situation, maybe I can reduce the duplication of the test cases, but is that a good practice to do the unit tests like this?
EDIT2:
I know I can test private methods because I used reflection in my other test cases, and I know it can invoke private methods, too. But my question is about in this situation, testing private methods is a proper solution or not.
This is actually a question I've wondered about for awhile, and while it's not necessarily correct, I'll share my opinion.
The main problem is that private methods are hard to test. I did some Googling, and there some tools and techniques that let you access private methods (reflection is the main one I encountered), but they seemed a little convoluted.
But the reason you wrote a private method is because there is another method, a public method, that calls it. So while you can't directly test the private method, you can check its functionality by testing the public method which calls it.
If I were you, I would extensively test methodA1() and methodA2(), ensuring that all the functionality of methodB() is tested by the tests you run on the public methods.
You've received a few opinions why you should write unit tests for methodA1() and methodA2(); you've pushed back on them. You asked the question here; you are clearly looking for some justification for not writing complete unit test for them. Let's see if we can give you the answer you want. ;-)
From what you've added in your edit, it looks like you have a variation on a builder pattern. Eg)
MyObject o = new Builder().setX(1).setY(2).setZ(3).setW(4).build();
How would we test the builder?
Since the builder has 4 attributes, which could be set in any order, there would be 4! = 24 different orderings. A complete test suite would have to include:
#Test public void testXYZW() { ... }
#Test public void testXYWZ() { ... }
// ... 21 more permutations ...
#Test public void testWZYX() { ... }
But is that all? No! Some of those attributes could have default values, so we would have to test those patterns as well. Total orderings is now P(4,4)+P(4,3)+P(4,2)+P(4,1)+P(4,0) = 24+24+12+4+1 = 85 unit test.
#Test public void testXWY() { ... }
#Test public void testWY() { ... }
#Test public void testZ() { ... }
// ... 61 more permutations ordering
And this only tests each permutation of X, Y, Z, W attributes with one test value per attribute per test. It is clearly unwieldy to write an exhaustive set of tests for every possible combination and permutation.
The designer of the builder class would understand that the permutation of the attribute settings does not affect the resulting construction; writing tests for permutations of the order does not actually increase the test coverage. Tests for omitted attributes are useful, as they test the default values. Testing of different combinations of the omitted attributes again would not increase the test coverage. So, after careful thought, only two tests might be required:
#Test
public void testXYZW() {
MyObject o = new Builder().setX(1).setY(2).setZ(3).setW(4).build();
assertThat(o.wasBuiltProperly());
}
#Test void testDefaults() {
MyObject o = new Builder().build();
assertThat(o.wasBuiltProperlyFromDefaults());
}
If proper, complete testing of methodB() is being done, then you could safely get away with testing only the validation of inputs in methodA1() and methodA2().
#Test void testMethodA1Professor() {
MyObject o = methodA1("professor");
assertThat(o.wasBuiltProperlyWithProfessor());
}
#Test void testMethodA1WithNull() {
MyObject o = methodA1(null);
assertThat(o.wasBuiltProperlyWithNull());
}
Oftentimes, when a private method is used by multiple methods inside a class, there's a distinct concept lurking behind it. It may deserve to have its own class.
it should not be used outside of the class
There are a few ways you could extract methodB to its own class and not make it available as part of your public API :
Nest it inside the class that uses it and give it a restricted scope
Put it in another module at a lower level. Make that module available from your API but not from the clients.

Mocking with functionality

I am very new to Mockito, please let me know if I'm on the right track. I'm trying to mock method functionality using Mockito.
sscce
public SUTclass {
private final DependencyInjectedObj dep; // already successfully mocked
private int statefulInteger;
private int otherInteger;
public int doSomething() {
return otherInteger + dep.doMath(statefulInteger);
}
}
Right now, dep is mocked... but dep.doMath always returns 0. In production, dep is stateful - no way to avoid it. In production, a different thread updates its state in real time. dep.doMath does some funky calculations depending on the state right now. You could imagine that production functionality might look at a thermometer and do something with it's temerature, and doSomething gives a realtime status based on that temperature.
In my test, though, I'd like to have dep.doMath have this functionality (which is a sufficient approximation for a unit test):
public int doMath(int input) {
return SOMECONSTANT * input;
}
I suppose I could create a Mock implementation of DependencyInjectedObj and use that, but that seems to defeat the purpose of using Mockito and the when syntax. What should I do?
In this case, what you want is doAnswer(). It allows you to execute arbitrary code when a mock invocation is called:
doAnswer(new Answer<Integer>() {
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
int i = (int)args[0];
return i * CONSTANT;
}
}).when(dep.doMath(any(Integer.class));
I do consider doAnswer a bit evil, though. Generally thenReturn(CONSTANT) is sufficient for most unit tests. If you're going to verify the result of this method call, then you're testing the wrong class -- the point of mocking your dependencies is you don't much care about their operation.

Mockito - Feeling that I don't use its full potential

When using Mockito, I only use it to mock out dependencies, i.e. my workflow looks mostly like this:
I have a class with dependencies:
public class C {
public C (A a, B b) {
this.a = a;
this.b = b;
}
public String fooBar() {
return a.foo() + b.bar();
}
}
In my test class, I mock out those dependencies, and tell them which values to return when some specified methods are called:
public class CSpec {
private A a = mock(A.class);
private B b = mock(B.class);
#Test
public itShouldReturnFooBar() {
when(a.foo()).thenReturn("foo");
when(b.bar()).thenReturn("bar");
C c = new C(a, b);
assertThat(c.fooBar().isEqualTo("foobar"));
}
}
(I hope this example is not too simple or too derived ;-)). This works fine, it allows me to test classes (here: C) in isolation. Still, I never use Mockito's verify methods or any other of its features. Is it okay / sufficient to use Mockito this way?
Verify would be typically used to check that your C really calls the A.foo() and B.bar() methods. So you could add
verify(a).foo();
verify(b).foo();
before or after the assertThat. I don't think you need or should use them here but there are several situations where you would need that:
a or b does something that is not visible / reachable from c's public API (for example logging)
You are concerned with the order of execution
You want to make sure that only a.foo and b.bar methods are called, nothing else like a.foo2
You could use those mocks as spy's, so that call to a.foo would be then routed to the aReal.foo
The verify approach is particularly useful in a Tell Don't Ask style of programming.
Consider the following version of your class C:
public class C {
public C(A a, B b, CListener L) { ... }
...
public void foobar() {
String result = complexPrivateMethod(a, b);
L.fooBarred(result);
}
}
Thus, rather than just computing the result, you inform some interested party (e.g. a user interface) about the result.
To test foobar now, you'd want to verify that the listener is correctly invoked:
public class CTest {
#Mock CListener mockListener;
...
#Test itShouldTellCAboutFooBar() {
C c = new C(stubbedA, stubbedB, mockedListener);
...
verify(mockedListener).fooBarred("foobar");
}
}
This use of verify is typical for Test-Driven Development: See Freeman & Pryce's Growing Object-Oriented Software Guided by Tests.
Thus, if you want to use the full potential of Mockito (the question), you most of all need to adopt the corresponding design philosophy in your code.
Yeah, there's no problem with this test, it's perfectly fine. The simple fact the the stubs are being used make the test working, if you remove or change the stubs then the test won't work.
Adding verify statements will just make things redundant in this kind of tests.
However if you precisely want to verify arguments, the order or number of interactions or something else then you definitely want to add checks on the interactions between the tested object and his collaborators.
It is totally ok to use Mockito just this way. But if your code gets more complex you need to do some more things to get your code tested as simple as possible.
Another small example:
public void eitherAorB() {
if(somethingIsTrue) {
a.doSomething();
} else {
b.doSomethingElse();
}
}
You might want to make sure, that the expected method is called on the expected object.
#Test
public doSomethingShouldBeCalledOnA() {
A a = mock(A.class);
C c = new C(a, new B());
c.setSomeThingIsTrue(true);
eitherAorB();
verify(a).doSomething();
}
#Test
public doSomethingElseShouldBeCalledOnB() {
B b = mock(B.class);
C c = new C(new A(), b);
c.setSomeThingIsTrue(false);
eitherAorB();
verify(b).doSomethingElse();
}
In other cases you might want to know which paramater was passed into a method. For that you need an ArgumentCaptor.
Or in some cases you need to call the actual method or use an actual object (no mock), so it is time to spy on an object and capture arguments or verify behavior.
So there is a lot more to Mockito you might need once in a while.
The answers given so far are good, but there are additional features you didn't mention either. The #Mock, #Spy, #InjectMocks annotations are all very useful. Along with the verify(...) methods, there is also the InOrder class to help verify the order of method calls. And perhaps you use the matcher methods already (<T> any(T t), anyString(), etc), but you don't show that you use those facilities.

Categories

Resources