Java, unit test mocking mxbean - java

I want to sort all the Java threads on CPU time. I use the ThreadMXBean to get the CPU time of the threads by thread ID. The comparator is used for sortinging the Thread ID's.
public class ThreadStats{
private static ThreadMXBean mxbean = ManagementFactory.getThreadMXBean();
class ThreadCPUCompare implements Comparator<Long>{
#Override
public int compare(Long threadId1, Long threadId2) {
return Long.compare(mxbean.getThreadCpuTime(threadId2), mxbean.getThreadCpuTime(threadId1));
}
}
}
And I've made the following unit test:
#RunWith(MockitoJUnitRunner.class)
public class ThreadStatsTest {
#InjectMocks ThreadCPUCompare comperator = new ThreadStats().new ThreadCPUCompare();
#Mock ThreadMXBean mxbean;
#Test
public void threadCPUSortTest() {
Mockito.when(mxbean.getThreadCpuTime(1L)).thenReturn(3L);
Mockito.when(mxbean.getThreadCpuTime(2L)).thenReturn(2L);
Mockito.when(mxbean.getThreadCpuTime(3L)).thenReturn(4L);
Mockito.when(mxbean.getThreadCpuTime(4L)).thenReturn(1L);
List<Long>expectedList = new ArrayList<Long>();
expectedList.add(3L);
expectedList.add(1L);
expectedList.add(2L);
expectedList.add(4L);
List<Long>actualList = new ArrayList<Long>();
actualList.add(4L);
actualList.add(2L);
actualList.add(3L);
actualList.add(1L);
//Sorting of the actual list
Collections.sort(actualList, comperator);
assertEquals(expectedList, actualList);
}
}
But I cant get the test to work. I think because the mocking doesn't work. Could someone show me how to fix the unit test please?

Your test is failing because the mock is not being injected. Mockito will not inject into static fields, nor will it inject into an outer class (such as the ThreadStats class in your case).
You need to write the code as something like this:
class ThreadCPUCompare implements Comparator<Long>
{
private ThreadMXBean mxbean;
#Override
public int compare(Long threadId1, Long threadId2) {
return Long.compare(mxbean.getThreadCpuTime(threadId2), mxbean.getThreadCpuTime(threadId1));
}
}
#RunWith(MockitoJUnitRunner.class)
public class ThreadStatsTest
{
#Mock ThreadMXBean mxbean;
#InjectMocks Comparator comperator = new ThreadCPUCompare();
#Test
public void threadCPUSortTest() {
// do your tests exactly as before
}
}
You will then have the challenge of wiring it into the production code, but that is a different exercise, where I would recommend some sort of dependency injection (guice, spring, manual etc depending on context and preferences).

One simple way to write the test is as follows, no mocking involved:
public class ThreadStatsTest {
Comparator<Long> comparator = new ThreadStats().new ThreadCPUCompare();
#Test
public void orderThreadIdsFromLongestToShortestCPUTime() {
long longLivedThread = Thread.currentThread().getId(); // > 0 cpu time
long shortLivedThread = new Thread().getId(); // 0 cpu time
int longTimeFirst = comparator.compare(longLivedThread, shortLivedThread);
int sameTimes = comparator.compare(longLivedThread, longLivedThread);
int longTimeSecond = comparator.compare(shortLivedThread, longLivedThread);
assertEquals(-1, longTimeFirst);
assertEquals( 0, sameTimes);
assertEquals( 1, longTimeSecond);
}
}

Related

Testing an abstract class with Mockito does not give the expected result

I have a class structure similar to the following
public abstract class AbstractStep {
private final Range RANGE;
AbstractStep(AbstractStepBuilder builder) {
RANGE = builder.range;
}
public abstract static class AbstractStepBuilder {
Range range;
public AbstractStepBuilder setRange(int start, end end) {
this.range = new Range(start, end);
return self();
}
abstract AbstractStepBuilder self();
}
public static class Range() {
private final int START;
private final int END;
private Range(int start, int end) {
if(start < 0 || end < 0 || start >= end)
throw new IllegalArgumentException();
START = start;
END = end;
}
}
}
I want to test setRange(int, int) in AbstractStepBuilder to see if the an IllegalArgumentException is thrown. I use TestNG and Mockito, and I have attempted the following using with the help of this.
final class RangeTest {
AbstractStepBuilder builder;
#BeforeSuite
void setup() {
builder = Mockito.mock(AbstractStepBuilder.class);
Mockito.when(builder.self()).thenReturn(null);
}
#Test(expectedExceptions = IllegalArgumentException.class)
final void testCreatingRangeWithNegativeStart() {
builder.setRange(-1, 2);
}
}
This test fails. I have also tried replacing Mockito.mock(AbstractStepBuilder.class) with Mockito.mock(AbstractStepBuilder.class, Mockito.CALLS_REAL_METHODS) as in the top answer of this question.
Note that if I make CodeRange as its own outer class, this test passes, so I do not believe it could be the test itself.
Why is this test failing, and is it possible to fix it without having to use a concrete class in the test instead?
You're calling a method on a mock, that will never throw an Exception until you tell it to. You never mock a class you want to test.
If you want to test the actual class, you'll need to create a subclass of the step builder, create an instance and test that.
I think you can also create a spy (by Mockito.spy(AbstractStepBuilder.class)) to avoid creating a subclass just for the test.

In Java, How to test void method in Junit Mockito with assertion?

How to test void methods in Mockito with assertSame or assertEquals. I am able to do verify only.
i am getting sonar or PMD rules violation -"JUnit tests should include assert() or fail()".
Below is my sample class with test class.
#Service
public class MyServiceImpl implements IService {
#Autowired
private IDyDBDAO dyDBDAO;
#Override
public void update() {
dyDBDAO.save(getDetailData());
}
#Override
public List<Detail> getCurrentDetail() {
return getDetails(dyDBDAO.findAll());
}
private List<Detail> getDetails(Iterable<Detail> details) {
...blah...
}
private String getPlace(){
Places p = Places.getPlace();//static
return p == null? PlacesUtil.getName("DH"): p.getName;
}
private Detail getDetailData() {
Detail d = new Detail();
d.setName("blah");
d.setDesc("fsdfsdfdsf");
d.setPlace(getPlace());
return d;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({Places.class, PlacesUtil.class})
public class MyServiceImplTest {
#InjectMocks
private MyServiceImpl myServiceImpl;
#Mock
private IDyDBDAO dyDBDAO;
#Test
public void testGetCurrentDetail() {
given(dyDBDAO.findAll()).willReturn(getMockDetails());
assertSame(myServiceImpl.getCurrentDetail().size(), 2);
}
#Test
public void testUpdate() {
PowerMockito.mockStatic(Places.class);
// first update , second update -us-west-2 will update
given(Places.getPlace()).willReturn(PlacesUtil.getName("UH"))
.willReturn(null);
myServiceImpl.syncStatus();
// update again with DH
myServiceImpl.syncStatus();
verify(dyDBDAO, times(2)).save(any(Detail.class));
// how to assert checking here
}
private Iterable<Detail> getMockDetails() {
Detail d1 = new Detail();
d1.setName("blah");
d1.setDesc("fsdfsdfdsf");
d1.setPlace("sdfsdf");
Detail d2 = new Detail();
d2.setName("blahblah1");
d2.setDesc("e345345");
d2.setPlace("8907j");
List<Detail> listOfDetail = new ArrayList<>();
listOfDetail.add(eps1);
listOfDetail.add(eps2);
return listOfDetail;
}
}
You need to capture the value passed to the dao save method. Use mockito's ArgumentCaptor for that. Then assert on that value.
Something along these lines:
ArgumentCaptor<Detail> captor = ArgumentCaptor.forClass(Detail.class);
verify(dyDBDAO, times(2)).save(captor.capture());
Detail detail1 = captor.getValues().get(0)
assertEquals(expectedDetail, detail1)
I would assume that your void method that needs to be tested is update in MyServiceImpl.
Firstly, you can verify if dyDBDAO.save() is called.
Mockito.verify(dyDBDAO).save(Mockito.anyList...);
Secondly, you can check the modified or created records in the database by retrieving them and comparing to the inputs from getMockDetails.

java mockito: is there a way to fake a class that doesnt exists?

I want to fake a new type of class that doesnt exist which implements an interface
is this possible?
for example, i have an interface
public interface Worker {
boolean execute(Job c);
}
I have a class
public class CompositeWorker implements Worker {
private List<Worker> childWorkers = new ArrayList<>();
public List<boolean> execute(Job j){
return childWorkers.stream().map(w -> w.execute(j)).collect(Collectors.toList());
}
public addWorker(Worker worker) {
childWorkers.add(worker)
}
}
To test:
public class CompositeWorkerTest {
private CompositeWorker worker;
#BeforeMethod
void setup() {
MockitoAnnotations.initMocks(this);
worker = new CompositeWorker();
}
#Test
test_worker() {
Worker worker_A = mock(Worker.class);
Worker worker_A = mock(Worker.class);
Job job = mock(Job.class);
when(worker_A.execute(job)).thenReturn(true);
when(worker_B.execute(job)).thenReturn(true);
worker.add(worker_A);
worker.add(worker_b);
List<boolean> results = worker.execute(job);
//assert results contains true
}
is there a way to fake/change Worker worker_A = mock(Worker.class); to FakeWorker fakeWorker = mock(FakeWorker.class) which implements Worker but it doesnt actually exists
by NOT exists, i mean there is no definition for:
public class FakeWorker implement Worker
the reason why I want to mock a different class is because Worker Type is unique
public addWorker(Worker worker) {
childWorkers = childWorkers.stream().filter(w -> w.getClass() != worker.getClass())
.collect(Collectors.toList());
childWorkers.add(worker)
}
First, chose names that make clear what's the system under test (sut) and what are mocked dependencies! Also, when using the .initMocks() method you don't need to call Mockito.mock() in many cases, just annotate class members as #Mock! In your case though I would recommend to create nested classes extending Worker in your test class:
public class CompositeWorkerTest {
interface WorkerA extends Worker {};
interface WorkerB extends Worker {};
#Mock
WorkerA workerAMock;
#Mock
WorkerB workerBMock;
#Mock
Job jobMock;
// systemm under test
private CompositeWorker sut;
#BeforeMethod
void setup() {
MockitoAnnotations.initMocks(this);
sut = new CompositeWorker();
}
#Test
void test_worker() {
when(workerAMock.execute(jobMock)).thenReturn(true);
when(workerBMock.execute(jobMock)).thenReturn(true);
sut.add(workerAMock);
sut.add(workerBMock);
List<boolean> results = sut.execute(jobMock);
//assert results contains true
}
}

Java - Testing Simulation With Mockito

I'm not very well-versed with Mockito but am trying to use mocks to test behaviour of a simulation, this is the class:
package simulator;
import java.util.Map;
import org.apache.commons.lang3.Validate;
import simulator.enums.Team;
import simulator.fixtures.Fixture;
public class SimulateBasketballMatchResult implements Simulation<Team> {
private final Fixture fixture;
public SimulateBasketballMatchResult(Fixture fixture) {
Validate.notNull(fixture, "fixture cannot be null");
this.fixture = fixture;
}
#Override
public Team simulate(Map<Team, Double> outcomeProbabilityMap) {
Validate.notNull(outcomeProbabilityMap, "outcomeProbabilityMap cannot be null");
final Team homeTeam = fixture.getHomeTeam();
final Team awayTeam = fixture.getAwayTeam();
double random = randomDoubleGenerator();
double homeWinProbability = outcomeProbabilityMap.get(homeTeam);
return random < homeWinProbability ? homeTeam : awayTeam;
}
public Double randomDoubleGenerator() {
return Math.random();
}
}
Below is the test class:
#RunWith(MockitoJUnitRunner.class)
public class SimulateBasketballMatchResultTest {
#Rule
public ExpectedException expectedException = ExpectedException.none();
private static final Map<Team, Double> MATCH_RESULT_PROBABILITY_MAP = new HashMap<>();
private static final Fixture FIXTURE = new Fixture(GOLDEN_STATE_WARRIORS, HOUSTON_ROCKETS, REGULAR_SEASON);
static {
MATCH_RESULT_PROBABILITY_MAP.put(FIXTURE.getHomeTeam(), 0.7d);
MATCH_RESULT_PROBABILITY_MAP.put(FIXTURE.getAwayTeam(), 0.3d);
}
#Mock
private SimulateBasketballMatchResult simulateBasketballMatchResult;
#Test
public void shouldReturnGoldenStateWarriorsAsWinner() {
when(simulateBasketballMatchResult.randomDoubleGenerator()).thenReturn(0.5d);
assertThat(simulateBasketballMatchResult.simulate(MATCH_RESULT_PROBABILITY_MAP), is(GOLDEN_STATE_WARRIORS));
}
}
I would like to assert that GOLDEN_STATE_WARRIORS is returned when the probability range is between 0 and 0.7- however I get an assertion error of null with my test code.
java.lang.AssertionError:
Expected: is <GOLDEN_STATE_WARRIORS>
but: was null
Expected :is <GOLDEN_STATE_WARRIORS>
simulateBasketballMatchResult is a mock object, so by default, it will return null for all its methods (that have a non-primitive return value, of course).
Instead of mocking that object, you should probably spy it:
#Spy
private SimulateBasketballMatchResult simulateBasketballMatchResult =
new SimulateBasketballMatchResult(Fixture);
Try this:
#Mock
private Fixture fixture;
private SimulateBasketballMatchResult simulator;
#Before
public void setUp() {
simulator = spy(new SimulateBasketballMatchResult(fixture));
doCallRealMethod().when(simulator).simulate();
}
#Test
public void shouldReturnGoldenStateWarriorsAsWinner() {
doReturn(0.5).when(simulator).randomDoubleGenerator();
when(fixture.getHomeTeam()).thenReturn(GOLDEN_STATE_WARRIORS);
when(fixture.getAwayTeam()).thenReturn(HOUSTON_ROCKETS);
assertThat(simulator.simulate(MATCH_RESULT_PROBABILITY_MAP), is(GOLDEN_STATE_WARRIORS));
}
Mockito.spy and #Spy allow you to mock some methods of a real object, but Mockito.mock and #Mock mock the whole object.
A mock in mockito is a normal mock (allows you to stub invocations; that is, return specific values out of method calls).
A spy in mockito is a partial mock (part of the object will be mocked and part will use real method invocations).
Read more

Switching from Mockito to JMockit

I used to rely on Mockito until today I have a final class with some static methods so I've to switched to JMockit. I knew nothing about it before so the question is: how can I apply the similar logic from Mockito to JMockit?
public final class ServiceData extends BaseData {
private List<Data> data;
public ServiceData(List<Data> data) {
this.data = data;
// something else
}
public static Container getContainer() {
return super.getContainer();
}
public Data getDataAt(Index index) {
return super.getContainer().get(index);
}
}
The test written in Mockito looks like:
#Test
public void test() {
ServiceData mockServiceData = mock(ServiceData.class);
Data mockData = mock(Data.class);
// only stubbing some of the methods
Container mockContainer = spy(Container.class);
doReturn(something).when(mockContainer.someMethod());
when(mockServiceData.getContainer()).thenReturn(mockContainer);
when(mockServiceData.getDataAt(any(Index.class)).thenReturn(mockData);
// some assertions
}
This won't work since Mockito cannot mock final classes nor static methods (getContainer)
So how can I write the same logic in JMockit? Thanks.
The following is the JMockit equivalent for the example test:
#Test
public void test(
#Mocked final ServiceData mockServiceData, #Mocked final Data mockData,
#Mocked final Container mockContainer)
{
// only stubbing some of the methods
new Expectations(mockContainer) {{
mockContainer.someMethod(); result = "something";
mockServiceData.getContainer(); result = mockContainer;
mockServiceData.getDataAt((Index) any); result = mockData;
}};
// some assertions
}
To mock static methods the syntax is the same, except that you would write ServiceData.getContainer(); result = mockContainer; instead.

Categories

Resources