Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Riena » Unit testing "ordinary" IController implementations(What's the best way to unit test controller classes that don't extend SubModuleController?)
icon5.gif  Unit testing "ordinary" IController implementations [message #543850] Wed, 30 June 2010 15:00 Go to next message
Christian Kesselheim is currently offline Christian Kesselheim
Messages: 59
Registered: June 2010
Member
Hi again,

just wanted to ask what's currently being considered the best way to unit test controller classes not extending SubModuleController. For example, how do I test AbstractWindowController implementations?

Using AbstractSubModuleControllerTest does clearly not qualify there, since the testing infrastructure relies on NavigationNodeController.getRidget(Class<R>, String) to create the dummy ridgets during our test.

Thanks in advance,

Chris

[Updated on: Wed, 30 June 2010 15:06]

Report message to a moderator

Re: Unit testing "ordinary" IController implementations [message #543971 is a reply to message #543850] Thu, 01 July 2010 04:52 Go to previous messageGo to next message
Christian Kesselheim is currently offline Christian Kesselheim
Messages: 59
Registered: June 2010
Member
For those who care: Here's the infrastructure code (read: hack) I use to test my AbstractWindowController.

All my window controllers extend AbstractTestableWindowController, while all corresponding unit tests inherit from AbstractControllerTest.

Please note that this only a work-around for current shortcomings in Riena itself. Here's my wish-list to make this unnecessary in the future:

* AbstractWindowController.getRidget(...) should behave similar to NavigationNodeController<ISubModuleNode>.getRidget(...) when invoked from within a unit test; that is: generate the (mock) ridgets automatically at the time they're first requested.
* There should be an equivalent to AbstractSubModuleControllerTest that people could use to unit test their AbstractWindowController sub-classes.
* All relevant Riena classes should always check for null when calling getUIControl() on their ridgets (e.g. EmbeddedTitleBarRidget.dispose() or DefaultActionManager.activate() currently fail to do so).

package lu.kreios.mtg.client.controllers;

import java.lang.reflect.Modifier;

import org.eclipse.core.runtime.Assert;
import org.eclipse.riena.core.RienaStatus;
import org.eclipse.riena.internal.ui.ridgets.swt.ShellRidget;
import org.eclipse.riena.ui.ridgets.ClassRidgetMapper;
import org.eclipse.riena.ui.ridgets.IActionRidget;
import org.eclipse.riena.ui.ridgets.IRidget;
import org.eclipse.riena.ui.ridgets.IWindowRidget;
import org.eclipse.riena.ui.ridgets.controller.AbstractWindowController;

@SuppressWarnings("restriction")
public class AbstractTestableWindowController extends AbstractWindowController {

	public static final String WINDOW_RIDGET = "windowRidget"; //$NON-NLS-1$

	public AbstractTestableWindowController() {
		// This becomes necessary due to the fact the EmbeddedTitleBarRidget fails
		// to check for getUIControl() returning null when called in the scope of 
		// its dispose() method. 
		ClassRidgetMapper.getInstance().addMapping(IWindowRidget.class, ShellRidget.class);		
	}
	
	@Override
	public void addDefaultAction(IRidget focusRidget, IActionRidget action) {
		// This becomes necessary due to the fact the DefaultActionManager fails
		// to check for getUIControl() returning null when called in the scope of 
		// its activate() method. We'll ignore this for now, since there's no 
		// chance of any unit test hitting the ENTER key after all.
	}
	
	@SuppressWarnings("unchecked")
	public <R extends IRidget> R getRidget(Class<R> ridgetClazz, String id) {
		R ridget = (R) getRidget(id);

		if (ridget != null) {
			return ridget;
		}
		if (RienaStatus.isTest()) {
			try {
				if (ridgetClazz.isInterface()
						|| Modifier.isAbstract(ridgetClazz.getModifiers())) {
					Class<R> mappedRidgetClazz = (Class<R>) ClassRidgetMapper
							.getInstance().getRidgetClass(ridgetClazz);
					if (mappedRidgetClazz != null) {
						ridget = mappedRidgetClazz.newInstance();
					}
					Assert.isNotNull(
							ridget,
							"Could not find a corresponding implementation for " + ridgetClazz.getName() + " in " + ClassRidgetMapper.class.getName()); //$NON-NLS-1$ //$NON-NLS-2$
				} else {
					ridget = ridgetClazz.newInstance();
				}
			} catch (InstantiationException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			}

			addRidget(id, ridget);
		}

		return ridget;
	}

	@Override
	public void setWindowRidget(IWindowRidget windowRidget) {
		super.setWindowRidget(windowRidget);
	}

	@Override
	public IWindowRidget getWindowRidget() {
		return getRidget(IWindowRidget.class, WINDOW_RIDGET);
	}

}


package lu.kreios.mtg.client.helpers;

import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.riena.core.RienaStatus;
import org.eclipse.riena.core.util.ReflectionUtils;
import org.eclipse.riena.internal.core.test.RienaTestCase;
import org.eclipse.riena.internal.core.test.collect.NonUITestCase;
import org.eclipse.riena.navigation.ui.controllers.SubModuleController;
import org.eclipse.riena.ui.ridgets.controller.IController;
import org.eclipse.riena.ui.ridgets.swt.uibinding.SwtControlRidgetMapper;
import org.eclipse.swt.widgets.Display;

/**
 * Abstract class for testing controllers that do NOT themselves extend {@link SubModuleController}.
 * In any other case, please consider using the standard {@link AbstractControllerTest} class from 
 * Riena itself.
 */
@NonUITestCase
@SuppressWarnings("restriction")
public abstract class AbstractControllerTest<C extends IController> extends RienaTestCase {

	private C controller;

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		System.getProperties().put(RienaStatus.RIENA_TEST_SYSTEM_PROPERTY, "true"); //$NON-NLS-1$

		// only used to get the initial mappings
		SwtControlRidgetMapper.getInstance();

		Display display = Display.getDefault();
		Realm realm = SWTObservables.getRealm(display);
		assertNotNull(realm);
		ReflectionUtils.invokeHidden(realm, "setDefault", realm); //$NON-NLS-1$

		controller = createController();

		controller.configureRidgets();
		controller.afterBind();
	}

	@Override
	protected void tearDown() throws Exception {
		System.getProperties().put(RienaStatus.RIENA_TEST_SYSTEM_PROPERTY, "false"); //$NON-NLS-1$
		super.tearDown();
	}

	protected C getController() {
		return controller;
	}

	protected abstract C createController();
}


[Updated on: Thu, 01 July 2010 10:30]

Report message to a moderator

Re: Unit testing "ordinary" IController implementations [message #544251 is a reply to message #543971] Fri, 02 July 2010 03:21 Go to previous message
Christian Campo is currently offline Christian Campo
Messages: 590
Registered: July 2009
Senior Member
Hi Christian,

why dont you open a bug in Riena, create a patch for a general solution to test AbstractWindowControllers and attach
that patch to the bug......

Thats open source and you are right in the middle of it :-)

christian


Am 01.07.10 10:52, schrieb Christian Kesselheim:
> For those who care: Here's the infrastructure code (read: hack) I use to
> test my AbstractWindowController.
>
> All my window controller extend AbstractTestableWindowController, while
> all corresponding unit tests inherit from AbstractControllerTest.
>
> Please note that this only a work-around for current shortcomings in
> Riena itself. Here's my wish-list to make this workaround unnecessary in
> the future:
>
> * AbstractWindowController.getRidget(...) should behave similar to
> NavigationNodeController<ISubModuleNode>.getRidget(...) when invoked
> from within a unit test; that is: generate the (mock) ridgets
> automatically at the time they're first requested.
> * There should be an equivalent to AbstractSubModuleControllerTest that
> people could use to unit test their AbstractWindowController.
> * All relevant Riena classes should always check for null when calling
> getUIControl() on their ridgets (e.g. EmbeddedTitleBarRidget.dispose()
> or DefaultActionManager.activate() currently fail to do so).
>
>
> package lu.kreios.mtg.client.controllers;
>
> import java.lang.reflect.Modifier;
>
> import org.eclipse.core.runtime.Assert;
> import org.eclipse.riena.core.RienaStatus;
> import org.eclipse.riena.internal.ui.ridgets.swt.ShellRidget;
> import org.eclipse.riena.ui.ridgets.ClassRidgetMapper;
> import org.eclipse.riena.ui.ridgets.IActionRidget;
> import org.eclipse.riena.ui.ridgets.IRidget;
> import org.eclipse.riena.ui.ridgets.IWindowRidget;
> import org.eclipse.riena.ui.ridgets.controller.AbstractWindowContro ller;
>
> @SuppressWarnings("restriction")
> public class AbstractTestableWindowController extends
> AbstractWindowController {
>
> public static final String WINDOW_RIDGET = "windowRidget"; //$NON-NLS-1$
>
> public AbstractTestableWindowController() {
> // This becomes necessary due to the fact the EmbeddedTitleBarRidget fails
> // to check for getUIControl() returning null when called in the scope
> of // its dispose() method.
> ClassRidgetMapper.getInstance().addMapping(IWindowRidget.cla ss,
> ShellRidget.class);
> }
>
> @Override
> public void addDefaultAction(IRidget focusRidget, IActionRidget action) {
> // This becomes necessary due to the fact the DefaultActionManager fails
> // to check for getUIControl() returning null when called in the scope
> of // its activate() method. We'll ignore this for now, since there's no
> // chance of any unit test hitting the ENTER key after all.
> }
>
> @SuppressWarnings("unchecked")
> public <R extends IRidget> R getRidget(Class<R> ridgetClazz, String id) {
> R ridget = (R) getRidget(id);
>
> if (ridget != null) {
> return ridget;
> }
> if (RienaStatus.isTest()) {
> try {
> if (ridgetClazz.isInterface()
> || Modifier.isAbstract(ridgetClazz.getModifiers())) {
> Class<R> mappedRidgetClazz = (Class<R>) ClassRidgetMapper
> .getInstance().getRidgetClass(ridgetClazz);
> if (mappedRidgetClazz != null) {
> ridget = mappedRidgetClazz.newInstance();
> }
> Assert.isNotNull(
> ridget,
> "Could not find a corresponding implementation for " +
> ridgetClazz.getName() + " in " + ClassRidgetMapper.class.getName());
> //$NON-NLS-1$ //$NON-NLS-2$
> } else {
> ridget = ridgetClazz.newInstance();
> }
> } catch (InstantiationException e) {
> throw new RuntimeException(e);
> } catch (IllegalAccessException e) {
> throw new RuntimeException(e);
> }
>
> addRidget(id, ridget);
> }
>
> return ridget;
> }
>
> @Override
> public void setWindowRidget(IWindowRidget windowRidget) {
> super.setWindowRidget(windowRidget);
> }
>
> @Override
> public IWindowRidget getWindowRidget() {
> return getRidget(IWindowRidget.class, WINDOW_RIDGET);
> }
>
> }
>
>
>
> package lu.kreios.mtg.client.helpers;
>
> import org.eclipse.core.databinding.observable.Realm;
> import org.eclipse.jface.databinding.swt.SWTObservables;
> import org.eclipse.riena.core.RienaStatus;
> import org.eclipse.riena.core.util.ReflectionUtils;
> import org.eclipse.riena.internal.core.test.RienaTestCase;
> import org.eclipse.riena.internal.core.test.collect.NonUITestCase;
> import org.eclipse.riena.navigation.ui.controllers.SubModuleControl ler;
> import org.eclipse.riena.ui.ridgets.controller.IController;
> import org.eclipse.riena.ui.ridgets.swt.uibinding.SwtControlRidgetM apper;
> import org.eclipse.swt.widgets.Display;
>
> /**
> * Abstract class for testing controllers that do NOT themselves extend
> {@link SubModuleController}.
> * In any other case, please consider using the standard {@link
> AbstractControllerTest} class from * Riena itself.
> */
> @NonUITestCase
> @SuppressWarnings("restriction")
> public abstract class AbstractControllerTest<C extends IController>
> extends RienaTestCase {
>
> private C controller;
>
> @Override
> protected void setUp() throws Exception {
> super.setUp();
> System.getProperties().put(RienaStatus.RIENA_TEST_SYSTEM_PRO PERTY,
> "true"); //$NON-NLS-1$
>
> // only used to get the initial mappings
> SwtControlRidgetMapper.getInstance();
>
> Display display = Display.getDefault();
> Realm realm = SWTObservables.getRealm(display);
> assertNotNull(realm);
> ReflectionUtils.invokeHidden(realm, "setDefault", realm); //$NON-NLS-1$
>
> controller = createController();
>
> controller.configureRidgets();
> controller.afterBind();
> }
>
> @Override
> protected void tearDown() throws Exception {
> System.getProperties().put(RienaStatus.RIENA_TEST_SYSTEM_PRO PERTY,
> "false"); //$NON-NLS-1$
> super.tearDown();
> }
>
> protected C getController() {
> return controller;
> }
>
> protected abstract C createController();
> }
>
>
>
Re: Unit testing "ordinary" IController implementations [message #586197 is a reply to message #543971] Fri, 02 July 2010 03:21 Go to previous message
Christian Campo is currently offline Christian Campo
Messages: 590
Registered: July 2009
Senior Member
Hi Christian,

why dont you open a bug in Riena, create a patch for a general solution to test AbstractWindowControllers and attach
that patch to the bug......

Thats open source and you are right in the middle of it :-)

christian


Am 01.07.10 10:52, schrieb Christian Kesselheim:
> For those who care: Here's the infrastructure code (read: hack) I use to
> test my AbstractWindowController.
>
> All my window controller extend AbstractTestableWindowController, while
> all corresponding unit tests inherit from AbstractControllerTest.
>
> Please note that this only a work-around for current shortcomings in
> Riena itself. Here's my wish-list to make this workaround unnecessary in
> the future:
>
> * AbstractWindowController.getRidget(...) should behave similar to
> NavigationNodeController<ISubModuleNode>.getRidget(...) when invoked
> from within a unit test; that is: generate the (mock) ridgets
> automatically at the time they're first requested.
> * There should be an equivalent to AbstractSubModuleControllerTest that
> people could use to unit test their AbstractWindowController.
> * All relevant Riena classes should always check for null when calling
> getUIControl() on their ridgets (e.g. EmbeddedTitleBarRidget.dispose()
> or DefaultActionManager.activate() currently fail to do so).
>
>
> package lu.kreios.mtg.client.controllers;
>
> import java.lang.reflect.Modifier;
>
> import org.eclipse.core.runtime.Assert;
> import org.eclipse.riena.core.RienaStatus;
> import org.eclipse.riena.internal.ui.ridgets.swt.ShellRidget;
> import org.eclipse.riena.ui.ridgets.ClassRidgetMapper;
> import org.eclipse.riena.ui.ridgets.IActionRidget;
> import org.eclipse.riena.ui.ridgets.IRidget;
> import org.eclipse.riena.ui.ridgets.IWindowRidget;
> import org.eclipse.riena.ui.ridgets.controller.AbstractWindowContro ller;
>
> @SuppressWarnings("restriction")
> public class AbstractTestableWindowController extends
> AbstractWindowController {
>
> public static final String WINDOW_RIDGET = "windowRidget"; //$NON-NLS-1$
>
> public AbstractTestableWindowController() {
> // This becomes necessary due to the fact the EmbeddedTitleBarRidget fails
> // to check for getUIControl() returning null when called in the scope
> of // its dispose() method.
> ClassRidgetMapper.getInstance().addMapping(IWindowRidget.cla ss,
> ShellRidget.class);
> }
>
> @Override
> public void addDefaultAction(IRidget focusRidget, IActionRidget action) {
> // This becomes necessary due to the fact the DefaultActionManager fails
> // to check for getUIControl() returning null when called in the scope
> of // its activate() method. We'll ignore this for now, since there's no
> // chance of any unit test hitting the ENTER key after all.
> }
>
> @SuppressWarnings("unchecked")
> public <R extends IRidget> R getRidget(Class<R> ridgetClazz, String id) {
> R ridget = (R) getRidget(id);
>
> if (ridget != null) {
> return ridget;
> }
> if (RienaStatus.isTest()) {
> try {
> if (ridgetClazz.isInterface()
> || Modifier.isAbstract(ridgetClazz.getModifiers())) {
> Class<R> mappedRidgetClazz = (Class<R>) ClassRidgetMapper
> .getInstance().getRidgetClass(ridgetClazz);
> if (mappedRidgetClazz != null) {
> ridget = mappedRidgetClazz.newInstance();
> }
> Assert.isNotNull(
> ridget,
> "Could not find a corresponding implementation for " +
> ridgetClazz.getName() + " in " + ClassRidgetMapper.class.getName());
> //$NON-NLS-1$ //$NON-NLS-2$
> } else {
> ridget = ridgetClazz.newInstance();
> }
> } catch (InstantiationException e) {
> throw new RuntimeException(e);
> } catch (IllegalAccessException e) {
> throw new RuntimeException(e);
> }
>
> addRidget(id, ridget);
> }
>
> return ridget;
> }
>
> @Override
> public void setWindowRidget(IWindowRidget windowRidget) {
> super.setWindowRidget(windowRidget);
> }
>
> @Override
> public IWindowRidget getWindowRidget() {
> return getRidget(IWindowRidget.class, WINDOW_RIDGET);
> }
>
> }
>
>
>
> package lu.kreios.mtg.client.helpers;
>
> import org.eclipse.core.databinding.observable.Realm;
> import org.eclipse.jface.databinding.swt.SWTObservables;
> import org.eclipse.riena.core.RienaStatus;
> import org.eclipse.riena.core.util.ReflectionUtils;
> import org.eclipse.riena.internal.core.test.RienaTestCase;
> import org.eclipse.riena.internal.core.test.collect.NonUITestCase;
> import org.eclipse.riena.navigation.ui.controllers.SubModuleControl ler;
> import org.eclipse.riena.ui.ridgets.controller.IController;
> import org.eclipse.riena.ui.ridgets.swt.uibinding.SwtControlRidgetM apper;
> import org.eclipse.swt.widgets.Display;
>
> /**
> * Abstract class for testing controllers that do NOT themselves extend
> {@link SubModuleController}.
> * In any other case, please consider using the standard {@link
> AbstractControllerTest} class from * Riena itself.
> */
> @NonUITestCase
> @SuppressWarnings("restriction")
> public abstract class AbstractControllerTest<C extends IController>
> extends RienaTestCase {
>
> private C controller;
>
> @Override
> protected void setUp() throws Exception {
> super.setUp();
> System.getProperties().put(RienaStatus.RIENA_TEST_SYSTEM_PRO PERTY,
> "true"); //$NON-NLS-1$
>
> // only used to get the initial mappings
> SwtControlRidgetMapper.getInstance();
>
> Display display = Display.getDefault();
> Realm realm = SWTObservables.getRealm(display);
> assertNotNull(realm);
> ReflectionUtils.invokeHidden(realm, "setDefault", realm); //$NON-NLS-1$
>
> controller = createController();
>
> controller.configureRidgets();
> controller.afterBind();
> }
>
> @Override
> protected void tearDown() throws Exception {
> System.getProperties().put(RienaStatus.RIENA_TEST_SYSTEM_PRO PERTY,
> "false"); //$NON-NLS-1$
> super.tearDown();
> }
>
> protected C getController() {
> return controller;
> }
>
> protected abstract C createController();
> }
>
>
>
Previous Topic:Unit testing "ordinary" IController implementations
Next Topic:How to build Riena from source?
Goto Forum:
  


Current Time: Fri Aug 22 02:08:40 EDT 2014

Powered by FUDForum. Page generated in 0.02265 seconds