JUnit - How to test a method with different values? - java

I have a method and wish to test it with different values. My question is: how can I write a JUnit test that would test the same method with different values?

You can take a look at parametrized tests like in example.
You can also use theories which is more convenient in a lot of cases.

JUnit4 supports parameterized tests for just this purpose.
See this tutorial.

I suggest you create a different unit test for each one of your (overloaded) function definitions, because arguably you are testing in fact different functions. For instance:
class MainClass {
public void method( int param) {... }
public void method( String param) { ...}
}
class MainClassTest {
#Test
public void methodIntTest() {
//call method(int)
}
#Test
public void methodStringTest() {
//call method(String)
}
}

Related

Java Unit tests using Mockito. Function call within a function

Suppose I have the following class :
public class Math {
public int mult(int a, int b) {
return 4;
}
public int mul (int a, int b) {
return mult(a,b);
}
}
And the following test class :
public class TestMockito {
Math testMath;
#Before
public void create () {
testMath = *mock*(Math.class);
when(testMath.mult(1,2).thenReturn(2);
}
#Test
public void test() {
System.out.println(testMath.mul(1,2));
}
}
Why does mul(1,2) called in test() not use when(testMath.mult(1,2).thenReturn(2); ?
Is there any other way to mock a method being used inside another method that is being tested ?
Cheers
You usually do not mock the code under test (unless it is an abstract class).
You usually mock other classes (the dependencies) your CUT communicates with.
The reason why your test does not work (as you expect) is that the mock is not an object of the real class (which is the reason why we mock it BTW....). It has been derived by the mocking framework not to behave like the original code but like it has been configured for the test.
If you really want the real methods being called in the mock (which is not what you want most of the time) you need to tell mockito that when creating the mock:
mock(ClassToBeMocked.class,Mockito.CALL_REAL_METHODS);

JUnit test if else case

How to write test to current method? I use jUnit 4.
public void setImage() {
if(conditionOne){
myView.setImageOne();
} else {
myView.setImageTwo();
}
}
You need to write two tests to cover both the scenarios as below:
import org.junit.Test;
public class SetImageTest {
#Test
public void testSetImageForConditionOne() {
//write test to make conditionOne true
}
#Test
public void testSetImageForElseCondition() {
//write test to make conditionOne false
}
}
Okay... there is a flaw in the way you wrote this method. There is something called testable code. Here is a link (how to write testable code and why it matters) that discusses testable code.
The method you wrote above is non-deterministic. Which means the method can exhibit different behaviors on different runs, even if it has the same input. In your case you have no input.
Currently, your original method is based on the environment of the method and not the input. This practice can make it very difficult and in some cases impossible to write proper test for your code.
So this is how you want it to look like...
public void setImage(boolean conditionOne) {
if(conditionOne){
myView.setImageOne();
} else {
myView.setImageTwo();
}
}
Now that the test is deterministic your either going to have to test the variables that are in the environment, or have a return statement.
So (adding a return statement) you can do this.
public static void setImage(boolean conditionOne, type myView) {
if(conditionOne){
myView.setImageOne();
} else {
myView.setImageTwo();
}
return myView;
}
Now your test can look something like this
public class SetImageTest {
#Test
public void testSetImage() {
type myViewOrig;
//define myViewOrig
type myView1;
//define myView1
type myView2;
//define myView2
assertEquals(setImage(<true>, type myViewOrig), myView1);
assertEquals(setImage(<false>, type myViewOrig), myView2);
}
}
Or you can just test the myView object after running your setImage method.

Call Variable length argument method in abstract class when using Mockito spy on subclass throws exception

I use Mockito 1.8.0 so I do not have AnyVararg. Upgrading to later version of Mockito is not on cards from my team at the moment. So please bear with me.
What the class looks like:
public abstract class Parent {
public void someMethod(String a, String b)
{
//.....
}
public void foo(String a, String... b)
{
//.....
}
}
public class Child extends Parent{
public void bar() {
someMethod(a,b);
foo(a,b,c);
methodToFailUsingSpy();
}
}
Unit tests
#Test
public void someTest() {
private spyOfChild = //initialize here;
doReturn("Something")).when(spyOfChild).methodToFailUsingSpy();
/* Tried using this, but did not help.
doCallRealMethod().when(spyOfChild).foo(anyString());
*/
spyOfChild.bar();
}
Problem -
When the spy sees someMethod(), it calls the real method in the abstract class. But when it sees foo(), it tries to find a matching stubbed method i.e control goes to Mockito's MethodInterceptorFilter, since it is not able to find a mock, it throws java.lang.reflect.InvocationTargetException.
I do not want foo() to be mocked. I want the real method to be called like it happens in someMethod(). Can someone explain if it is because of using method with variable length arguments with a spy?
This is a bug in Mockito.
https://groups.google.com/forum/#!msg/mockito/P_xO5yhoXMY/FBeS4Nf4X9AJ
Your example is quite complicated, to reproduce the problem is very simple:
class SimpleClass {
public String varargsMethod(String... in) {
return null;
}
public void testSpyVarargs() {
SimpleClass sc = Mockito.spy(new SimpleClass());
sc.varargsMethod("a", "b");
}
}
Even this will produce the error you describe, and the workaround suggested in the link doesn't work for me.
Unfortunately to get around this you will need to upgrade Mockito. Changing to version 1.9.5 makes the above run fine, plus you get the varargs matchers as you say (although note that your problem isn't to do with matchers but how Mockito handles spied varargs methods).
I don't think there were too many huge changes between 1.8.0 and 1.9.5, it shouldn't be too painful.

same unit test for different implementations

Let's say I have two implementations of a search algorithm that return the same result for the same input. They both implement the same interface.
How can I use a single [TestClass] for testing both implementations, rather then create two test files with eventually the same logic ?
Can I tell MSUnit to launch one of the tests twice with different constructor parameter?
Perhaps I should (n)inject it somehow ?
Use an abstract test class:
[TestClass]
public abstract class SearchTests
{
private ISearcher _searcherUnderTest;
[TestSetup]
public void Setup()
{
_searcherUnderTest = CreateSearcher();
}
protected abstract ISearcher CreateSearcher();
[TestMethod]
public void Test1(){/*do stuff to _searcherUnderTest*/ }
// more tests...
[TestClass]
public class CoolSearcherTests : SearcherTests
{
protected override ISearcher CreateSearcher()
{
return new CoolSearcher();
}
}
[TestClass]
public class LameSearcherTests : SearcherTests
{
protected override ISearcher CreateSearcher()
{
return new LameSearcher();
}
}
}
You've tagged your question with NUnit, but you ask about MSTest. What you are asking about can be achieved with parameterized test fixtures in NUnit. I am not familiar enough with MSTest to suggest an equivalent approach there, and a quick search indicates that MSTest may not have this feature.
In NUnit you parameterize the test fixture by applying multiple [TestFixture(...)] attributes to the fixture class with different parameters. These parameters will be passed to the fixture constructor.
Since there are limits on the types of parameter that can be passed, you'll probably need to pass a string in specifying the algorithm, then in the constructor assign the delegate or object that provides the search algorithm to a member field which is used in the tests.
For example:
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace MyTests
{
public static class SearchAlgorithms
{
public static int DefaultSearch(int target, IList<int> data)
{
return data.IndexOf(target);
}
public static int BrokenSearch(int target, IList<int> data)
{
return 789;
}
}
[TestFixture("forward")]
[TestFixture("broken")]
public class SearchTests
{
private Func<int, IList<int>, int> searchMethod;
public SearchTests(string algorithmName)
{
if (algorithmName == "forward")
{
this.searchMethod = SearchAlgorithms.DefaultSearch;
return;
}
if (algorithmName == "broken")
{
this.searchMethod = SearchAlgorithms.BrokenSearch;
}
}
[Test]
public void SearchFindsCorrectIndex()
{
Assert.AreEqual(
1, this.searchMethod(2, new List<int> { 1, 2, 3 }));
}
[Test]
public void SearchReturnsMinusOneWhenTargetNotPresent()
{
Assert.AreEqual(
-1, this.searchMethod(4, new List<int> { 1, 2, 3 }));
}
}
}
I'd rather have two different [TestMethod] in one [TestClass] each testing only one implementation: this way a failing test will always correctly point you which implementation went wrong.
If you are using NUnit you can pass through a variable declared in an attribute
http://www.nunit.org/index.php?p=testCase&r=2.5.6
if you use something like:
[TestCase(1)]
[TestCase(2)]
public void Test(int algorithm)
{
//..dostuff
}
if will run once for 1, once for 2, uses the same setup/teardown too :)
There isn't an equivalent in MSTest however you can fudge it somewhat as explained here:
Does MSTest have an equivalent to NUnit's TestCase?
I can't say I'm extremely happy with this approach, but here's what I ended up doing. I then went to look for a better approach and found this question. This approach meets the criteria, 1) I'm using MS Test, 2) I write the test logic only 1 time, 3) I can tell which implementation failed (and double clicking on the test will take me to the right test class).
This approach uses a base class to contain all the actual test logic, and then a derived class for each implementation (I have 3) that sets the specific implementation on the base interface and overrides the base test methods.
[TestClass]
public abstract class SearchTestBase
{
protected ISearcher Searcher { get; set; }
[TestMethod]
public virtual void Find_Results_Correct()
{
// Arrange (code here)
// Act (single line here)
var actual = Searcher.Results(input);
// Assert
}
}
(different file...)
[TestClass]
public class FastSearcherTest : SearcherTestBase
{
[TestInitialize]
public void TestInitialize()
{
Searcher = new FastSearcher();
}
[TestMethod]
public override void Find_Results_Correct()
{
base.Find_Results_Correct();
}
}
(different file...)
[TestClass]
public class ThoroughSearcherTest : SearcherTestBase
{
[TestInitialize]
public void TestInitialize()
{
Searcher = new ThoroughSearcher();
}
[TestMethod]
public override void Find_Results_Correct()
{
base.Find_Results_Correct();
}
}
So what I don't like about this approach is that every time I want to add a test I need to go to each of the test files and override the new test method. What I do like are the 3 requirements you had. If I need to change a test, I change the logic in just one place.
The advantage I see to this solution over the similar one of having a single method called by two tests is that I don't have to repeat the code for setting up the right implementation. In this solution you have a single line that calls the base.TestName(), and not two lines, one to set the Searcher and another to call the test. The Visual Studio also makes writing this much faster... I just type, "override" and get a list of choices. Auto complete writes the rest for me.
Clarifications based on my testing.
The accepted answer (to use an abstract class) works as long as the abstract class and concrete classes are in the same assembly.
If you desire to have the abstract class and concrete classes in different assemblies, the approach mentioned by KarlZ, unfortunately seems to be necessary. Not sure why this is the case. In this scenario, the TestExplorer will not show TestMethod.
Also, the accepted answer uses concrete classes nested within the abstract class. This does not appear to be a requirement.
Test with MSTestV2 (1.1.17), VS2017.
Here are sample classes used.
Assembly 1
[TestClass]
public abstract class SampleExternal
{
[TestMethod]
public void SampleTest01()
{
Assert.IsTrue(false, this.GetType().Name);
}
}
Assembly 2
[TestClass]
public abstract class Sample
{
[TestMethod]
public void SampleTest01()
{
Assert.IsTrue(false, this.GetType().Name);
}
[TestClass]
public class SampleA : Sample
{
}
}
[TestClass]
public class SampleB : Sample
{
}
[TestClass]
public class SampleC : SampleExternal
{
}
[TestClass]
public class SampleD : SampleExternal
{
}
using these, the test for SampleA and SampleB will execute (and fail by design), but SampleC & SampleD will not.

Changing method execution in runtime (Java)

I am a Software Engineer in Test, and I am trying to write code that can replace production side method so that test can execute those instead. Basically, I do not want to modify production code for testability.
Here is a simple scenario:
public class Foo {
public static void foo() {
printA();
}
public static void printA() {
System.out.println("A");
}
public static void printB() {
System.out.println("B");
}
}
public class Foobar {
public Foobar() {
}
public void test() {
Foo.foo();
}
public static void main(String[] args) {
//Try changing the method here
new Foobar().test();
}
}
As you can see, when the main executes, it will print "A" since it calls the method printA on static method foo(). Now on runtime, is there a way I can inject or modify such that foo will call printB instead of printA?
Thank you for all the help!
Look at AspectJ.
It provides advices, which can be used to execute some code around a method (before and after its execution), including bypassing the call to original method altogether and returning some arbirary value
If you're just doing this for testing out classes, you could use a mocking framework to mock the classes on the server. I like Mockito.
You can do it yourself using the java reflection api, or you can you use a tool like PowerMock.

Categories

Resources