Unitils breaks standard EasyMock behavior? - junit

In a project at work I came across a real annoying bug/feature. I found a sollution however I'm really curious to the why it is happening. It all has to do that the project has some legacy tests written with unitils instead of plain old EasyMock. Consider following two test classes ran in order right behind eachother.
public class Test1{
#TestedObject
private MyService myService;
#InjectIntoByType protected Mock<MyRepository> myRepo;
#Test
public void aTest(){
myService.doSomething();
myRepo.assertNotInvoked().getById(EasyMock.anyLong());
}
}
public class Test2{
private IMocksControl control;
private MyOtherService myService;
private MyOtherRepo myRepo;
public Test2(){
control = EasyMock.createControl();
myRepo = control.createMock(MyOtherRepo.class);
myService = new MyOtherService(myRepo);
}
#Test
public void aTest(){
myRepo.getById(5L);
EasyMock.expectLastCall().andReturn(new MyObject(5L));
control.replay()
MyObject result = myService.doSomething();
control.verify()
Assert.assertEquals(5L,result.getId().longValue);
}
}
When I run both test seperatly they run fine. Both green both working. However if I run them right after eachother the second test fails with
java.lang.IllegalStateException: x matchers expected, y recorded error (x and y are ints ofcourse, just since this is a fake example I don't have real numbers).
I "fixed" this by changing the assertNotInvoked line to : myRepo.assertNotInvoked().getById(null);
This is ofcourse not really a fix, I just circumvented the use of matchers and I'm wondering if I just didn't break the legacy test case with it ... Is there anyone with enough EasyMock + Unitils experience that could help me understand this ? My best "guess" is that AssertNotInvoked isn't properly ended with a EasyMock.replay(), EasyMock.verify() block ... but I could be wrong.

Related

Messy diagram derives when it comes to printing it on pdf by using MS Windows 10 service

I've been writing Java SE 8 desktop application. I use Eclipse IDE, Oracle's JDK, and run it on MS Windows 10 OS.
My app draws diagrams, in short. I draw a diagram on JPanel which becomes part of JTabbedPane. It displays it well on GUI, and it is very responsive. The problem shows up when I pass the diagram on printing service. But instead of printing it on printer, I choose, "Microsoft print to PDF" service. What happens next, is that if the diagram is large, when you scroll it down, you will observe that its quality drops down. That is, grids start disappearing, new lines appear, etc.
The pic out here.
As you can see, eventually vertical grids vanish, diagonal line creeps in, and later gets even worse. And that is unwelcome.
Relevant code in here:
public final class GanttChartDiagram extends TopDiagram{
#Override
public void paintComponent(Graphics graph){
super.paintComponent(graph);
Graphics2D g2D = (Graphics2D)graph;
g2D.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
...........
#Override
public Dimension getPreferredSize(){
return new Dimension(this.diagramWidth + 20, this.diagramHeight + 20);
}
}
}
The getPreferredSize() method identifies the size of diagram, so that the app knows how to adjust the scroll-bars accordingly to fit the diagram in. Otherwise by default it return 0, if not overridden.
That is the class where I draw the diagram.
The super-class out here:
public abstract class TopDiagram extends JPanel implements Printable {
private static final long serialVersionUID = 1469816888488484L;
#Override
public void paintComponent(Graphics graph){
super.paintComponent(graph);
};
/**
* Prints selected diagram
*/
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
Graphics2D dimension = (Graphics2D)graphics;
dimension.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
if(pageIndex < PrintingImageBuffer.getImageBuffer().size()){
dimension.drawImage(PrintingImageBuffer.getImageBuffer().get(pageIndex), null, 0, 0);
return PAGE_EXISTS;
}
else{
return NO_SUCH_PAGE;
}
}
}
Now that is where I print the diagram:
public static void printDiagram(){
new Thread(new Runnable(){
public void run(){
TopDiagram diagram = null;
if(id.equalsIgnoreCase("GanttChart")){
diagram = ganttChartDiagram;
}
final PrinterJob printer = PrinterJob.getPrinte
rJob();
printer.setJobName("Printing the "+id+" Diagram");
PageFormat format = printer.pageDialog(page);
int nowWidth = (int)diagram.getPreferredSize().getWidth();
int nowHeight = (int)diagram.getPreferredSize().getHeight();
BufferedImage buffImg = new BufferedImage(nowWidth, nowHeight, BufferedImage.TYPE_INT_ARGB);//default type
Graphics2D d = (Graphics2D)buffImg.getGraphics();
....etc..................
}
}).start();
}
Now the interesting part is this:
int nowWidth = (int)diagram.getPreferredSize().getWidth();
int nowHeight = (int)diagram.getPreferredSize().getHeight();
On the same instance of diagram, on multiple invocations of print (or within the method), it may or may not return different values. So that it was causing me some sort of Raster exception. But I managed to get rid off of that exception by invoking size method only once and reusing that size value throughout the method. So that, the size value stays the same, cause it is read only once.
Bad solution, but it works.
I would like to solve this issue too. Firstly, how come that this invocation diagram.getPreferredSize().getWidth() on the same instance of diagram obj. returns different size value? One more thing, is that I overrode this method as has been presented above. And the diagram object is created only once, no recalculations.
This is where I create the diagram obj. on Swing Worker only once per application's life-cycle.
GanttChartSwingWorker ganttSwingWorker = new GanttChartSwingWorker(GanttChartDiagram::new, tabbedPane, showPerformanceDiagramTab, ganttChartDiagramTabReady);
ganttSwingWorker.execute();
new Thread(() -> {
try{
ganttChartDiagramTabReady.await();
ganttChartDiagram = ganttSwingWorker.getGanttChartDiagram();
}catch(InterruptedException ie){ie.printStackTrace();}
}
).start();
Swing Worker part:
diagram = this.get();
JScrollPane scrollPaneChart = addScrollPane(diagram);
tabbedPane.addTab("Gantt Chart", null, scrollPaneChart, "Displays Gantt Chart Diagram");
Some diagram objects can be time consuming to create, imposes delay, so I use Swing Worker to do that.
So, in summary:
How to make the diagram to appear clean when I print/save it on pdf file in the way that I explained?
How to make the diagram size to calculate consistently as per multiple invocations? What leads to different diagram size values retrieving it from the same diagram object instance on multiple calls?
I just figured out what the problem is.
I observed that when it comes to drawing the diagram, the
paintComponent(Graphics g) method has been invoked repeatedly. It keeps redrawing the diagram over and over again. It is invoked by the system implicitly, yet my implementation had been triggering it.
And that trigger comes in the form of this.setSize(width, height) method on derived JPanel object. So that each time the paintComponent(Graphics g) re-executes, it sets the size on JPanel which yet triggers additional execution of the painComponent method. In the end, it is an infinite loop.
And that infinite execution was the cause of the problem; it was producing distorted diagram image on pdf file.
Solution: execute the setSize method only when it is needed; on initial panel set-up, or resize.

Is it possible in LibGDX's `scene2d` API to have the same Actor instance in multiple Stages?

I am making a program using the amazing libGDX+scene2d API and I structured it as follows:
I have a single MyGame instance, holding a single PolygonSpriteBatch instance.
There is an abstract MyScreen class, holding a MyStage class (see below)
Then there are lots of different screen classes that inherit from MyScreen, and instantiate each other at will.
(in all cases, removing the "My" gives you the name of the respective library class that it extends)
This model worked fine, until I encountered some problems to perform actions between screens using the Action system. I decided then that it would be a good idea to have a single OmnipresentActor belonging to MyGame that, as the name says, is present in every scene. So I modified MyStage to look more or less like this:
public class MyStage extends Stage {
public MyStage(MyGame g) {
super(new FitViewport(MyGame.WIDTH, MyGame.HEIGHT), g.batch);
addActor(game.omnipresentInvisibleActor);
}
#Override
public void clear() {
unfocusAll();
getRoot().clearActions();
getRoot().clearListeners();
removeActorsButNotListenersNorActions();
}
public void removeActorsButNotListenersNorActions() {
for (Actor a : getActors()) if (a.getClass()!= OmnipresentInvisibleActor.class) a.remove();
}
It followed a painful debugging phase, until I found out the following:
public PresentationScreen(MyGame g) {
// super() call and other irrelevant/already debugged code
System.out.println("PRINT_BEFORE: "+ stage.getActors().toString()); // OmnipresentActor is there
mainMenuScreen = new MainMenuScreen(game);
System.out.println("PRINT_AFTER: "+ stage.getActors().toString()); // OmnipresentActor is not there anymore, but was added to the mainMenuScreen
the "PRINT_BEFORE" statement shows that the stage holds the omnipresentActor. In "PRINT_AFTER" it isn't there anymore, whereas mainMenuScreen is indeed holding it. So my question, now more precise:
does scene2d prevent this to happen, or am I doing something wrong here?
Answers much appreciated! Cheers
An actor can only be a member of one stage: Thanks to #Tenfour04 for confirming that. The explanation is quite clear after doing a little research:
Stage.addActor() looks like this:
(here the github code of Stage.java)
/** Adds an actor to the root of the stage.
* #see Group#addActor(Actor) */
public void addActor (Actor actor) {
root.addActor(actor);
}
whereas root is simply initialized as a group in the Stage constructor: root = new Group();.
And Group.addActor() looks like this:
(here the github code of Group.java)
/** Adds an actor as a child of this group. The actor is first removed from its parent group, if any. */
public void addActor (Actor actor) {
if (actor.parent != null) actor.parent.removeActor(actor, false);
children.add(actor);
actor.setParent(this);
actor.setStage(getStage());
childrenChanged();
}
So in the tree first lines is the answer: when creating the new stage, if the actor to add already has a parent, it is removed from its current parent. So, There are two possible solutions to the problem I enounced:
SOLUTION 1: Override addActor removing the if statement, or any other alteration of the library, which I'm not sure if it would work. I rather think this could be very problematic, for instance it could prevent the stages from disposing correctly
SOLUTION 2: Change the design so you don't need an omnipresent actor, nor changing/reimplementing the libraries. For the moment this is what I've done based on this answer, it isn't very clean but it works so far:
1) In the MyScreen class added the following fields:
private boolean watchingTemp;
private Actor watchActorTemp;
private Action actionTemp;
2) Then added this method:
public void addActionOnStageAfterActorEndsHisActions(Actor actor, Action action) {
watchActorTemp = actor;
actionTemp = action;
watchingTemp = true;
}
3) then in the render method, I added the following:
if (watchingTemp && !watchActorTemp.hasActions()) {
watchingTemp = false;
stage.addAction(actionTemp);
}
4) finally, when wishing to perform an action at a screen transition (and eventually disposing the first one), you can do something like this: I use something similar when clicking on a door between screens
public void movePlayerTHENgotoNewScreen(float xPos, float yPos, whatever else...) {
game.player.walkToAnyPoint(xPos, yPos);
yourFavoriteScreen.addActionOnStageAfterActorEndsHisActions(game.player, gotoNewScreen(wathever else...));
}
Hope it helps!

Using UniversalTweenEngine with LibGDX music

Short question...
How do I correctly use UniversalTweenEngine with the Music class in LibGDX?
Long question...
I've encountered a problem with using UniversalTweenEngine and the Music class in LibGDX. I have a MusicAccessor that implements TweenAccessor like so:
public static final int VOLUME = 0;
#Override
public int getValues(Music target, int tweenType, float[] returnValues) {
switch(tweenType) {
case VOLUME:
returnValues[0] = target.getVolume();
return 1;
default:
assert false;
return -1;
}
}
#Override
public void setValues(Music target, int tweenType, float[] newValues) {
switch(tweenType) {
case VOLUME:
target.setVolume(newValues[0]);
break;
default:
assert false;
}
}
first I used it like this:
Tween.registerAccessor(Music.class, new MusicAccessor());
myMusicInstance.setVolume(0);
Tween.to(myMusicInstance, MusicAccessor.VOLUME, 1f).target(1).start();
Which gave me an error saying that
No TweenAccessor was found for the target
I read some on the problem and saw people having the same issue, and the answer to this question told me that I had to use .cast(Music.class) as well, so i changed it to this:
Tween.to(myMusicInstance, MusicAccessor.VOLUME, 1f).cast(Music.class).target(1).start();
which no longer gives me the error. The snag with this is that it doesn't actually tween any value! I've added TweenCallbacks and done System.out.println("text") in the TweenAccessor's methods, and found out that they aren't being called. So how am I supposed to do for it to work?
I reproduced your problem and managed to fix it, so here is a solution.
First of all you need an instance of TweenManager. Then don't forget to start your music (it won't start by itself). Your MusicAccessor class is ok, so no need to change anything there. The final code snippet:
an instance field
private TweenManager tweenManager = new TweenManager();
constructor (or wherever you used it)
Tween.registerAccessor(Music.class, new MusicAccessor());
myMusicInstance.setVolume(0);
myMusicInstance.play();
and then in render:
tweenManager.update(delta);
Tween.to(music, MusicAccessor.VOLUME, 1f).cast(Music.class).target(1).start(tweenManager);
If anything is unclear, please let me know.

How to do CreateBindingSet() on Windows Phone?

In the N+1 video #34 (Progress), there was an example of using CreateBindingSet() for the Android version, which is not typical. But the narrator also mentioned briefly that the same can be done on the Windows platform.
As much as I tried, however, I am unable to get a View's property to be bound to its ModelView on the Windows Phone. I always get a NullReferenceException.
The closest I came was the code below, including suggestions from ReSharper. Here's my FirstView.xaml.cs:
using Cirrious.MvvmCross.Binding.BindingContext;
using Whatever.ViewModels;
namespace Whatever {
// inheriting from IMvxBindingContextOwner was suggested by ReSharper also
public partial class FirstView : BaseView, IMvxBindingContextOwner {
public class MyBindableMediaElement
{
private string _theMediaSource = "whatever";
public string TheMediaSource
{
get
{
return _theMediaSource;
}
set
{
_theMediaSource = value;
}
}
}
public FirstView()
{
InitializeComponent();
_mediaElement = new MyBindableMediaElement(this.theMediaElement);
var set = this.CreateBindingSet<FirstView, FirstViewModel>();
// the corresponding view model has a .SongToPlay property with get/set defined
set.Bind(_mediaElement).For(v => v.TheMediaSource).To(vm => vm.SongToPlay);
set.Apply();
}
public IMvxBindingContext BindingContext { get; set; } // this was suggested by ReSharper
}
I get a NullReferenceException in MvxBaseFluentBindingDescription.cs as soon as the view is created. The exact location is below:
protected static string TargetPropertyName(Expression<Func<TTarget, object>> targetPropertyPath)
{
var parser = MvxBindingSingletonCache.Instance.PropertyExpressionParser; // <----- exception here**
var targetPropertyName = parser.Parse(targetPropertyPath).Print();
return targetPropertyName;
}
I have not seen a working example of creating a binding set on a Windows Phone emulator. Has anyone gotten this to work? Thanks.
I can confirm that the narrator said that remark a little too flippantly without actually thinking about how he might do it...
However, with a little effort, you definitely can get the CreateBindingSet to work in Windows if you want to.
Before you start, do consider some alternatives - in particular, I suspect most people will use either Windows DependencyProperty binding or some hand-crafted code-behind with a PropertyChanged event subscription.
If you do want to add CreateBindingSet code to a Windows project then:
Add the Binding and BindingEx assemblies to your Ui project - the easiest way to do this is using nuget to add the BindingEx package.
In your Setup class, override InitializeLastChance and use this opportunity to create a MvxWindowsBindingBuilder instance and to call DoRegistration on that builder. Both these first two steps are covered in the n=35 Tibet binding video - and it's this second step that will initialise the binding framework and help you get past your current 'NullReferenceException' (for the code, see BindMe.Store/Setup.cs)
In your view, you'll need to implement the IMvxBindingContextOwner interface and you'll need to ensure the binding context gets created. You should be able to do this as simply as BindingContext = new MvxBindingContext();
In your view, you'll need to make sure the binding context is given the same DataContext (view model) as the windows DataContext. For a Phone Page, the easiest way to do this is probably just to add BindingContext.DataContext = this.ViewModel; to the end of your phone page's OnNavigatedTo method. Both steps 3 and 4 could go in your BaseView if you intend to use Mvx Binding in other classes too.
With this done, you should be able to use the CreateBindingSet code - although do make sure that all binding is done after the new MvxBindingContext() has been created.
I've not got a windows machine with me right now so I'm afraid this answer code comes untested - please do post again if it does or doesn't work.
I can confirm it works almost perfectly; the only problem is, there are no defaults register, so one has to do the full binding like:
set.Bind(PageText).For(c => c.Text).To(vm => vm.Contents.PageText).OneTime();
to fix this, instead of registering MvxWindowsBindingBuilder, I am registering the following class. Note: I have just created this class, and needs testing.
public class UpdatedMvxWindowsBindingBuilder : MvxWindowsBindingBuilder
{
protected override void FillDefaultBindingNames(IMvxBindingNameRegistry registry)
{
base.FillDefaultBindingNames(registry);
registry.AddOrOverwrite(typeof(Button), "Command");
registry.AddOrOverwrite(typeof(HyperlinkButton), "Command");
//registry.AddOrOverwrite(typeof(UIBarButtonItem), "Clicked");
//registry.AddOrOverwrite(typeof(UISearchBar), "Text");
//registry.AddOrOverwrite(typeof(UITextField), "Text");
registry.AddOrOverwrite(typeof(TextBlock), "Text");
//registry.AddOrOverwrite(typeof(UILabel), "Text");
//registry.AddOrOverwrite(typeof(MvxCollectionViewSource), "ItemsSource");
//registry.AddOrOverwrite(typeof(MvxTableViewSource), "ItemsSource");
//registry.AddOrOverwrite(typeof(MvxImageView), "ImageUrl");
//registry.AddOrOverwrite(typeof(UIImageView), "Image");
//registry.AddOrOverwrite(typeof(UIDatePicker), "Date");
//registry.AddOrOverwrite(typeof(UISlider), "Value");
//registry.AddOrOverwrite(typeof(UISwitch), "On");
//registry.AddOrOverwrite(typeof(UIProgressView), "Progress");
//registry.AddOrOverwrite(typeof(IMvxImageHelper<UIImage>), "ImageUrl");
//registry.AddOrOverwrite(typeof(MvxImageViewLoader), "ImageUrl");
//if (_fillBindingNamesAction != null)
// _fillBindingNamesAction(registry);
}
}
This is a skeleton from Touch binding, and so far I have only updated three controls to test out (Button, HyperButton and TextBlock)

How to use Behavior class with Swing events?

I'm writing code for a 3D graph, and I want the scene graph to update when the user presses a JButton. I'm trying to use a Behavior class, but I can't find any information on using swing events to wake up the behavior. I would REALLY appreciate any help! Thank you!!
You can use a special behavior object which contains a queue of Runnables. You can then post runnables to the behaviour and wake it up. You will have to sort out proper synchronisation so the behaviour only goes to sleep when there are no more commands in the queue, but it should work.
Make the class into a singleton to be able to run Runnable's inside the BehaviorScheduler, analogous to the SwingUtilities.invokeLater() method.
public class ThreadTransferBehavior extends Behavior {
private final static int POST_ID = 9997;
private final WakeupOnBehaviorPost m_wakeupPost = new WakeupOnBehaviorPost(this, POST_ID);
private final Stack<Runnable> commands;
public synchronized void processStimulus(Enumeration i) {
while(!commands.isEmpty()) commands.pop().run();
wakeupOn(m_wakeupPost);
}
public synchronized void queueCommand(Runnable r) {
commands.push(r);
postId(POST_ID);
}
}