I am just trying to go through with Spock test framework and as per the documentation it looks better than JUnit and tried to write the simple test case but somehow it's not working.
Class:
public class SwapTwoNumber {
public void swapNumber(int a,int b){
a =a+b;
b=a-b;
a=a-b;
}
}
Spock Test Groovy:
import spock.lang.Specification
class SwapTwoNumberTest extends Specification{
def "swap to number as given. #a and #b"() {
given:
int a = 5
int b = 6
when:
SwapTwoNumber sw =Mock()
sw.swapNumber(a,b)
then:
a==6
b==5
}
}
I am not familiar with the testing framework you mentioned but this is most likely not a framework problem. You are passing primitives arguments.
As stated in the docs
Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost.
I am looking for a way to test the data in a class that processes the data and then uploads the data in a manner as clean and portable as possible. So I would like to not resort to making public get functions, to avoid anything being able to reach this data. To keep it portable, I would like to avoid using a test database, so that these tests can be ran in any situation.
Class Foo {
private int a;
private int b;
private int c;
private DBSaver dbSaver;
public Foo(DBSaver dbSaver) {
this.dbSaver = dbSaver;
}
public void processData() {
processData();
saveToDB();
}
private void workNumbers() {
a = 1;
b = 2;
c = a + b;
}
private void saveToDB() {
List<Integer> list = new ArrayList<>();
list.add(a); list.add(b); list.add(c);
dbSaver.save(list);
}
}
Test class:
class FooTest {
#Mock
DBSaver dbSaver;
#Mock
Foo foo;
#Test
private void test() {when(dbSaver.save(any(ArrayList<>.class))).then(returnsFirstArg());
foo = new Foo(dbSaver);
Mockito.doThrow(new Exception() {
//Now I would like to get a, b and c so I can ensure that they have the proper values.
}
).when(foo).processData();
}
}
Here is a pastebin version of the code]().
workNumbers() will be executed as normal, and since the save() function has been mocked to do nothing, that code won't do anything too serious.
I would like to ask if there is a way to now get the a, b and c values back in list form, through mocking an exception being thrown. The problem is accessing the private values in Foo through the mocked instance in FooTest.
You are getting unit testing with mocking wrong. There is no point in having this:
#Mock
Foo foo;
Foo is your "class under test". You do not want to mock that. If at all, you might want to create a spy here, in order to do partial mocking.
In your case, you don't need to access those private fields. You see, the key point is that your code will call:
dbSaver.save(list);
at some point. Meaning: you can use Mockitoy to verify that a specific list is passed when save() is called on that mocked dbSaver object.
That is the whole point: you have that mocked dbSaver instance, so you are in total control what happens there. As said, you can verify that its methods are called with a specific argument; or you can even use an ArgumentCaptor in order to access the list passed to that method call.
And then you simply ensure that the list contains the expected content (which would be those three values from your class under test!). See
here for examples how to do that.
Finally: especially that "exception" part is really wrong. There is no need to generate an exception here. You simply push a mocked dbSaver into an instance of Foo, you call a method on that Foo instance; and then you check for the expected results. That's it; anything else is (useless) over-complication of things.
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.
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.
I just want to know is there a way in junit or with the help of any mocking frameworks,to just test the constructor of a class.In a way to just test whether a constructor is invoked like how we test for a method is invoked using verify,can we apply it to constructor.I have seen in many post,where people test the constructor by testing the value of the fields in the class after constructor initialization.
Like
Public ClassName{
private Class x;
#Inject
ClassName(Class x){
this(x.getObjDriver);
}
ClassName(Driver d){
do something...
}
public int getValueOfX{
return x;
}
and in the test class they test this constructor ClassName by calling the construcotr with a argument value for x and then using the getValueOfX method in their assert statement to check the value of x thereby somehow testing the constructor call.
I was thinking doing this in a way not using this approach
is there a way to test the ClassName(Class x) constructor? And also verify in the process the ClassName(Driver d) constructor was also called?