How to Unit Test a Utility Class with Powermockito in Java - java

I've seen how to unit test classes that use Utility classes by mocking the Static method, but I haven't been able to figure out how to unit test the actual Utility Class.
Here is the Utility Class
public class DbNameContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDbName(String dbName){
contextHolder.set(dbName);
}
public static String getDbName(){
return (String) contextHolder.get();
}
public static void clearDbName(){
contextHolder.remove();
}
}
Here is what I've tried so far for a unit test
#RunWith(PowerMockRunner.class)
#PrepareForTest({DbNameContextHolder.class, ThreadLocal.class})
public class DbNameContextHolderTest {
#SuppressWarnings("rawtypes")
#Mock
ThreadLocal threadLocalMock;
#Before
public void init() throws Exception{
PowerMockito.whenNew(ThreadLocal.class).withNoArguments().thenReturn(threadLocalMock);
}
#Test
public void setsDBName(){
DbNameContextHolder.setDbName("someName");
verify(threadLocalMock).set("someName");
}
#Test
public void getsDbName(){
DbNameContextHolder.getDbName();
verify(threadLocalMock).get();
}
#Test
public void clearsDBName(){
DbNameContextHolder.clearDbName();
verify(threadLocalMock).remove();
}
}
How do I mock a utility class like this?

Using the suggestions in the comments I've tested the expected outcome.
#RunWith(MockitoJUnitRunner.class)
public class DbNameContextHolderTest {
#Test
public void setsAndGetsDBNameCorrectly(){
DbNameContextHolder.setDbName("someName");
String returnedName = DbNameContextHolder.getDbName();
assertEquals("someName",returnedName);
}
#Test
public void clearsDBName(){
DbNameContextHolder.setDbName("someName");
String returnedName = DbNameContextHolder.getDbName();
assertEquals("someName",returnedName);
DbNameContextHolder.clearDbName();
returnedName = DbNameContextHolder.getDbName();
assertNull(returnedName);
}
}

Related

JUnit parameterized and non-parameterized tests with PowerMockito

So I am trying to run JUnit parameterized tests along with non-parameterized tests in the same test class. But I am running into one error or the other. Has anyone tried this before and were they successful in doing so? I know other runners need to be used with the #PowerMockRunnerDelegate in order to run correctly. So here's what I came up with:
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(Enclosed.class)
#PrepareForTest(Some.class)
#PowerMockIgnore("javax.management.*")
public class TestClass {
#PowerMockRunnerDelegate(Parameterized.class)
public static class ParameterizedTests {
}
#Test
public void nonParameterizedTestOne() {
}
#Test
public void nonParameterizedTestTwo() {
}
}
But I get the error:
Test class should have exactly one public zero-argument constructor
Without powermock, this situation can be easily handled with:
#RunWith(Enclosed.class)
public class TestClass {
#RunWith(Parameterized.class)
public static class ParameterizedTests {
}
#Test
public void nonParameterizedTestOne() {
}
#Test
public void nonParameterizedTestTwo() {
}
}
But I would definitely like to use powermock. Any solutions?
I had the same issue, this worked for me:
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(Enclosed.class)
#PrepareForTest({Some.class})
public class TestClass {
private static void setUpOnceForAllTests() {
}
private static void setUpForEveryTest() {
}
public static class SingleTests {
// Setup once for all single tests
#BeforeClass
public static void setUpBeforeClass() {
setUpOnceForTests();
}
// Setup for each and every single test
#Before
public void setUp() {
setUpForEveryTest();
}
#Test
public void nonParameterizedTestOne() {
}
#Test
public void nonParameterizedTestTwo() {
}
}
#PowerMockRunnerDelegate(Parameterized.class)
public static class ParameterizedTests {
// Setup once for all parameterized test
#BeforeClass
public static void setUpBeforeClass() {
setUpOnceForTests();
}
// Setup for each and every parameterized test
#Before
public void setUp() {
setUpForEveryTest();
}
#Parameterized.Parameters
public static Collection<Enum> param() {
return new ArrayList<>(Arrays.asList(Enum.values()));
}
#Parameterized.Parameter
public int param;
#Test
public void parameterizedTestOne() {
}
#Test
public void parameterizedTestTwo() {
}
}
}

Can I mock some static methods only using powermock+mockito+junit?

I am writing a test using Junit + Mockito + Powermock.
I have a class like following which I want to test:
public class MyUtils {
public static Object method1() {} //I want to mock this only
public static void method2() {} //I want to keep this as is during my test.
public static void method3() {} //I want to keep this as is during my test.
}
I want to mock only method1 but not method2 or method3.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyUtils.class)
public class MyTest {
#Before
public void setUpBeforeClass() throws Exception {
PowerMockito.mockStatic(MyUtils.class);
}
#Test
public void test1() throws Exception {
when(MyUtils.method1()).thenReturn(something);
MyUtils.method3(); //method3 is getting mocked with an empty implementation by PowerMockito
}
...
}
Can I have some methods mocked and some not be mocked i.e. they keep their original implementation during the test? Is this possible with Mockito + Powermock?
My test may not look very elegant but I have simplified my usecase before posting here.
Thank you.
Yes it is possible to mock static methods using Powermock and JUnit as below:
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.powermock.api.mockito.PowerMockito.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest(IDGenerator.class)
public class UserDAOTest {
#Test
public void createShouldReturnAUserId() {
UserDAO dao = new UserDAO();
mockStatic(IDGenerator.class);
when(IDGenerator.generateID()).thenReturn(1);
int result = dao.create(new User());
assertEquals(1, result);
verifyStatic();
}
}
public final class IDGenerator {
static int i;
public static final int generateID() {
return i++;
}
}
public class UserDAO {
public int create(User user){
int id = IDGenerator.generateID();
//Save the user object to the db
return id;
}
}
public class User {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Hope it helps!
If you have way more methods that you want to keep with real implementation than ones that need to be mocked (especially when its only one in your case) then I would go for spy instead of mock:
import static org.powermock.api.mockito.PowerMockito.spy;
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyUtils.class)
public class MyTest {
#Before
public void setUpBeforeClass() throws Exception {
spy(MyUtils.class);
}
#Test
public void test1() throws Exception {
doReturn(something).when(MyUtils.class, "method1");
MyUtils.method3(); // this will be a real call
}
...
}
Now all the methods except method1 will be called with real implementation.

Powermock and Mockito. Avoid static initialization for a class while mocking and stubing the same class

Suppose I have a class named Util with static fields:
public class Util {
public static field = Param.getValue("param1");
}
and the class Param look like this:
public class Param {
public static field = SomeClass.getValue("someValue");
}
I want to mock and stubb Param.getValue("param1") inside Util, but at the same time I want suppress static initialization for Param class. How can I achieve this?
This is my first attempt but it's not working
#RunWith(PowerMockRunner.class)
#PrepareForTest({Param.class})
#SuppressStaticInitializationFor("py.com.company.Param")
public class Test {
#Test
public void testSomeMethod() {
PowerMockito.mockStatic(Param.class);
when(Param.getValue("value1")).thenReturn("someValue1");
}
}
This is working for me. I get no output, and SomeClass#getValue if no #SuppressStaticInitializationFor:
#RunWith(PowerMockRunner.class)
#SuppressStaticInitializationFor({"so35047166.Param"})
#PrepareForTest({Param.class})
public class UtilTest {
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(Param.class);
}
#Test
public void testFoo() throws Exception {
final Util util = new Util();
assertEquals("Util#foo", util.foo());
assertEquals(null, Util.field);
}
}
with:
// all in package so35047166;
public class Util {
public static String field = Param.getValue("param1");
public String foo() {
return "Util#foo";
}
}
public class Param {
public static String field = SomeClass.getValue("someValue");
public static String getValue(final String in) {
System.out.println("Param#getValue");
return "Param#getValue";
}
}
public class SomeClass {
public static String getValue(final String in) {
System.out.println("SomeClass#getValue");
return "SomeClass#getValue";
}
}

SetUp/TearDown methods in sahi tests using junit framework

Is it possible to place the setup/teardown methods using JUnit framework in a single class (which would be my baseclass) so on test runs they methods are always called first/last? it would be in a similar way to which nunit tests can be structured
currently the only way I can get my tests to kick off is if I have the setup/teardown methods within the same class as my tests are (which is something I wan't to avoid, to keep my test classes tidy)
example I would hope to set up;
public class baseclass
{
#Before
public void setUp
{}
#After
public void tearDown
{}
}
public class tests
{
#Test
public void test1
{
// test content here
}
}
Run this test and see the sequence of events
class Test1 {
#Before
public void setUp1() {
System.out.println("setUp1");
}
}
public class Test2 extends Test1 {
#Before
public void setUp2() {
System.out.println("setUp2");
}
#Test
public void test() {
System.out.println("test");
}
}
Yes, as long as your test class extend your baseclass.
For instance:
Suite
#RunWith(Suite.class)
#SuiteClasses(Tests.class)
public class AllTests {
}
BaseClass
public class BaseClass {
#BeforeClass
public static void beforeAll() {
}
#Before
public void setUp() {
}
#After
public void tearDown {
}
#AfterClass
public static void afterAll() {
}
}
Tests
public class Test extends BaseClass {
#Test
public void test1() {
}
#Test
public void test2() {
}
}

Is it possible to create nested unit test using junit and mockito?

For example:
#RunWith(MockitoJUnitRunner.class)
public class ClientFormServiceTest {
#Mock
ClientFormService clientFormService;
public class GetNewClientFormTest {
#Mock
protected ClientForm result;
#Before
public void given() {
result = clientFormService.getNewForm();
}
#Test
public void should_do_something() {
}
}
public class CreateClientFormTest {
#Mock
protected ClientForm clientForm;
#Before
public void given() {
clientFormService.createForm(clientForm);
}
#Test
public void should_do_something() {
}
}
}
This is what I want to do but I can't run the unit tests if are nested to a class.
I'm the author of a JUnit TestRunner, junit-nested, which I believe may do what you want: https://github.com/avh4/junit-nested
However, from your example it's not clear why you need nested tests. The typical reason to use them is to share setup behavior, but you should consider if having separate test classes is more appropriate.
In any case, here's how you can do it with junit-nested: (Since Nested is a test runner, you'll have to use MockitoAnnotations.initMocks() instead of the Mockito test runner.)
import net.avh4.test.junit.Nested;
#RunWith(Nested.class)
public class ClientFormServiceTest {
#Mock
ClientFormService clientFormService;
#Before
public void given() {
MockitoAnnotations.initMocks(this);
}
public class GetNewClientFormTest {
#Mock
protected ClientForm result;
#Before
public void given() {
MockitoAnnotations.initMocks(this);
result = clientFormService.getNewForm();
}
#Test
public void should_do_something() {
}
}
public class CreateClientFormTest {
#Mock
protected ClientForm clientForm;
#Before
public void given() {
MockitoAnnotations.initMocks(this);
clientFormService.createForm(clientForm);
}
#Test
public void should_do_something() {
}
}
}
Why would you like to do that? If you mean to benefit from code reuse among many similar tests, you could come up with a base test class with common code and make test classes extend it.

Categories