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.
Related
I came across an answer on how to use Retry in Selenium web driver test. Now I have implemented Retry class under utilities and inside the test annotation given as follows #Test(retryAnalyzer = Retry.class). This is working fine now, but I would like to change this way, can I use the Retry in any other way instead of giving in test annotation as #Test(retryAnalyzer = Retry.class) ? Also I need to comment the #Test(enabled = true), Can someone please advise ?
utilities/Retryclass
public class Retry implements IRetryAnalyzer {
private int retryCount = 0;
private int maxRetryCount = 2;
public boolean retry(ITestResult result) {
if(retryCount < maxRetryCount) {
retryCount ++ ;
return true;
}
return false;
}
}
tests/RepaymentCalculatorTest
public class RepaymentCalculatorTest extends BaseTest {
Retry retryTest = new Retry();
//#Test(enabled = true)
#Test(retryAnalyzer = Retry.class)
public void loanRepaymentCalculator() throws InterruptedException {
// rest of the UI test code added here ....
}
i am using bit different way, no need to add class in #Test annotation
Lets have custom Listener for it
public class RetryFailedTestCases implements IRetryAnalyzer, IAnnotationTransformer{
public void transform(ITestAnnotation testannotation, Class testClass, Constructor testConstructor,
Method testMethod) {
testannotation.setRetryAnalyzer(RetryFailedTestCases.class);
}
int counter = 0;
int retryLimit = 1; //as per need
#Override
public boolean retry(ITestResult result) {
if(counter < retryLimit)
{
counter++;
return true;
}
return false;
}
}
Now, add this in testng.xml file
<listeners>
<listener class-name="package.RetryFailedTestCases"/>
</listeners>
this is simple and helpful when we run as suite.. alternative we can mentioned listener class on top of each class instead of testng.xml file
i am not sure why explicitly mentioned enabled = true ? even if not #Test execute right? if you dont want to execute then mention with false.
I have writen an annotation (in a spring boot application) and try to apply it to the call() method of Callable, but it doesn't work, yet on the other hand, when applied to a normal method (please see code below), it works, this keeps bothering me, could you please give me some clues? Thank you very much.
Here are my code,
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface LogExecutionTime {
}
#Aspect
#Component
public class LogExecutionTimeAspect {
private static final Logger logger = LoggerFactory.getLogger(LogExecutionTimeAspect.class);
#Around("#annotation(LogExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
final long start = System.currentTimeMillis();
final Object proceed = joinPoint.proceed();
final long executionTime = System.currentTimeMillis() - start;
logger.info(joinPoint.getSignature() + " executed in " + executionTime + "ms");
return proceed;
}
}
public class DummyCallable implements Callable<Integer> {
private Integer start, count;
DummyCallable() {}
DummyCallable(Integer start, Integer count) {
this.start = start;
this.count = count;
}
#LogExecutionTime // not working...
#Override
public Integer call() throws Exception {
Thread.sleep(start * 1000);
Integer sum = 0;
for (Integer i = start; i <= start + count; i++) {
sum += i;
}
return sum;
}
}
#LogExecutionTime // This will work...
public List<Integer> getAllUserScores() {
Callable c1 = new DummyCallable(1, 100000);
Callable c2 = new DummyCallable(2, 100000);
Callable c3 = new DummyCallable(3, 100000);
// .... run them ...
return result;
}
Inspired by #sbjavateam, I realize that three things,
spring aop work only with object that are managed by spring container. To apply aspect for your class it should be a bean or component and instantiated by spring context. (All right, this is copied from #sbjavateam's answer.)
Based on the former statement, Callable c1 = new DummyCallable(1, 100000); is wrong by nature, since we must create the DummyCallable from the spring context (so that bean will be properly injected with it's dependencies), calling new is not capable.
The DummyCallable class needs to have a scope of prototype so that it is not a singleton. The singleton scope is the default scope for a Spring bean. As a result, this class must have this annotation: #Scope("prototype").
Below is my fix,
#Component
#Scope("prototype")
public class DummyCallable implements Callable<Integer> {}
private DummyCallable createDummyCallable(Integer start, Integer end) {
return context.getBean(DummyCallable.class, start, end);
}
Besides, you might want this configuration as well,
spring.aop.proxy-target-class=true
Last but not least, thank you very much, #sbjavateam.
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);
}
}
Is there any way in java to check if a certain method was called inside another method? I am testing a class and the method I am having trouble with plays sound and there is virtually no way of getting the audio file that is played(private attribute inside an inner class) without changing the code. However the way the method plays sounds is it calls a method that plays a single sound (playSadMusic, playHappyMusic, etc). Those methods are in an interface that I have to create a mock object for. I'm a little stuck on how I would exactly go about testing this. Any thoughts? Any other ideas on how I could possibly test this other than check if a certain method was call are welcome.
I am using JMock 2.6.0 and JUnit 4
the audio inteface
public interface StockTickerAudioInterface {
public abstract void playHappyMusic();
public abstract void playSadMusic();
public abstract void playErrorMusic();
}
anther interface I have to create a mock for
public interface StockQuoteGeneratorInterface {
public abstract StockQuoteInterface getCurrentQuote() throws Exception;
public abstract String getSymbol();
public abstract void setSymbol(String symbol);
public abstract StockQuoteGeneratorInterface createNewInstance(String symbol);
}
the class being tested
public class StockQuoteAnalyzer {
private StockTickerAudioInterface audioPlayer = null;
private String symbol;
private StockQuoteGeneratorInterface stockQuoteSource = null;
private StockQuoteInterface lastQuote = null;
private StockQuoteInterface currentQuote = null;
public StockQuoteAnalyzer(String symbol,
StockQuoteGeneratorInterface stockQuoteSource,
StockTickerAudioInterface audioPlayer)
throws InvalidStockSymbolException, NullPointerException,
StockTickerConnectionError {
super();
// Check the validity of the symbol.
if (StockTickerListing.getSingleton().isValidTickerSymbol(symbol) == true){
this.symbol = symbol;
} else {
throw new InvalidStockSymbolException("Symbol " + symbol
+ "not found.");
}
if (stockQuoteSource == null) {
throw new NullPointerException(
"The source for stock quotes can not be null");
}
this.stockQuoteSource = stockQuoteSource;
this.audioPlayer = audioPlayer;
}
public double getChangeSinceLast() {
double retVal = 0.0;
if (this.lastQuote != null) {
double delta = this.currentQuote.getLastTrade() - this.lastQuote.getLastTrade();
retVal = 100 * (delta / this.lastQuote.getLastTrade());
}
return retVal;
}
public double getChangeSinceYesterday() {
double delta = (this.currentQuote.getLastTrade() - this.currentQuote
.getClose());
return 100 * (delta / this.currentQuote.getClose());
}
public void playAppropriateAudio() {
if ((this.getChangeSinceYesterday() > 2)
|| (this.getChangeSinceLast() > 0.5)) {
audioPlayer.playHappyMusic();
}
if ((this.getChangeSinceYesterday() < -2)
|| (this.getChangeSinceLast() < -0.5)) {
audioPlayer.playSadMusic();
}
}
}
If you use Mockito you can use verify() to check the number of times a method was called. Use it like this:
verify(mockedObject, times(1)).methodToValidate();
You can check if methodToValidate() was called with a specific string, e.i verify(mockedObject, times(1)).methodToValidate("a specific value"); or you can use it with anyString() like this: verify(mockedObject, times(1)).methodToValidate(anyString());.
Unless this method is called with your specified paramterer, the test will fail
Read more about verify here.
UPDATE
Since your edited post states that you are using jMock, a quick googeling showed me that it is possible to achieve a similar behaviour with jMock and it's expect method. It's used as below:
mockedObject.expects(once()).method("nameOfMethod").with( eq("An optional paramter") );
More detailed explanation can be found by reading jMocks getting started page.
say you have a method child() which is called in parent()
public void parent() {
child();
}
In child() to get the last method it got invoked from, you can use StackTraceElement
public void child() {
StackTraceElement[] traces = Thread.currentThread().getStackTrace();
boolean check = false;
for(StackTraceElement element : traces) {
if(check) {
System.out.println("Calling method - " + element.getMethodName());
}
if(element.getMethodName().equals("child")) {
check = true;
}
}
}
If you are writing a mock object with the methods you want to check whether they were called, you can implement the methods in a way they raise some flag when they are called, for example
public void playHappyMusic() {
this.wasCalled = true;
}
wasCalled being a public (or with getters) class variable. Then you just check the flag.
Provide you are in the same thread as the calling method, you can check the stack trace in any given moment this way:
Thread.currentThread().getStackTrace()
You can see what method are called doing it like this:
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
For example:
public class Test {
public static void main (String[]s){
Test test = new Test();
test.makeTest();
}
public void makeTest(){
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
}
results in
java.lang.Thread.getStackTrace(Unknown Source)
Test.makeTest(Test.java:17)
Test.main(Test.java:11)
Hello all
I have a piece of software that I would like to run many different times, each for a particular value of a class field that is set in the class's constructor.
E.g, somewhere in the code is something along the lines of
public class Stuff
{
private double importantVal;
public Stuff(double val)
{
this.importantval = val;
}
public double doStuff()
{
return 4 * importantVal;
}
}
This class and method is very far down in the program/call-stack, so I can't merely call doStuff several times by itself.
I would like to test the program for various values of importantVal, perhaps by placing them in a file and iterating over them. I worked out the easy bit of running the program many times , but I have no good idea of how to substitute different values of importantVal. If all else fails I can always write a script that modifies the source code, but that feels ugly and ad-hoc. Is there a more elegant solution involving injection, or something along those lines?
To illustrate what the folks are trying to tell you here, here's how the testcases might look like:-
public class StuffTest {
#Test
public void testDoStuff_Zero(){
Stuff stuff = new Stuff(0);
assertEquals(0, stuff.doStuff());
}
#Test
public void testDoStuff_One(){
Stuff stuff = new Stuff(1);
assertEquals(4, stuff.doStuff());
}
#Test
public void testDoStuff_NegativeValue(){
Stuff stuff = new Stuff(-10);
assertEquals(-40, stuff.doStuff());
}
#Test
public void testDoStuff_PositiveValue(){
Stuff stuff = new Stuff(10);
assertEquals(40, stuff.doStuff());
}
#Test
public void testDoStuff_DecimalValue(){
Stuff stuff = new Stuff(1.1);
assertEquals(4.4, stuff.doStuff());
}
}
public class StuffRunner {
public static void main(String[] args) {
double x = 0.0d;
for (int i = 0; i < 100; ++i) {
Stuff s = new Stuff(x);
if (s.doStuff() != 4 * x) {
System.out.print("Error, unexpected value. X=");
System.out.println(x);
}
x = x + 1.22;
}
}
}
do you have multiple instances of the Stuff class? if not, perhaps you could try "injecting" the values by making importantVal static? or to inject multiple values use a List?
public class Stuff{
private static List<Double> testVals = new LinkedList()<Double>;
private double importantVal;
public Stuff(double val)
{
this.importantval = val;
}
public static addTest(double test){
testVals.add(test);
}
public double doStuff()
{
return 4 * testVals.removeFirst();
}
}