4

My application uses a genetic algorithm for evolving neural networks. In developing unit tests for the (randomised) mutation algorithm I wish to ensure that for given random values the correct mutations occur.

In the question here the most popular answer to the question of unit testing algorithms that involve randomness is to use mocking. This seems very sensible to me but my question is whether anyone has solid suggestions about how to do this.

Here is how I currently achieve this. I define an interface for my randomness generator (highly simplified here for illustration purposes):

public interface Mutator { float randomSynapseWeightChange(); float randomSynapseThresholdChange(); } 

In the main application this interface has an implementation that wraps Random. In my unit testing framework I use:

public class TestMutator implements Mutator { List<Float> synapseWeightChanges = new ArrayList<>(); public void addTestSynapseWeightChange(float weightChange) { synapseWeightChanges.add(weightChange); } public float randomSynapseWeightChange() { return synapseWeightChanges.remove(); } } 

My unit tests then look like:

@Test public void testDecreaseSynapseWeightMutation() { TestMutator mutator = new TestMutator(); mutator.addTestSynapseWeightChange(-0.5); world.setMutator(mutator); Synapse synapse = new Synapse(new Neuron(), 0.1); synapse.mutate(); assertEquals("Weight has decreased during mutation", -0.4, synapse.getWeight()); } 

This is really not a particularly elegant solution. The unit test relies on knowing how many random numbers the code is going to need. For tests that involve several mock random numbers being pushed onto the list it pretty unclear when reading it later what each of the numbers of for.

So my question is has anyone come across a neater way of doing this? Would I be better off having an enum to define the different domains of randomness (or even different classes of Mutators) to document the meaning of the mocked numbers better?

1 Answer 1

5

Use a mock framework such as mockito. With it you can do this:

// static import for Mockito.xxx needed final Mutator mutator = mock(Mutator.class); // Will return value1, then value2 when(mock.randomSynapseWeightChange()) .thenReturn(value1) .thenReturn(value2) .etc().etc(); 

You can even cook your own Answers if you need to return a more "complex" set of numbers than just specifying them all (for instance you want to cycle through a list of specified numbers).

Note that with the .thenReturn() example above, if you call the method three times then the returned values will be v1, v2, v2; four times, v1, v2, v2, v2. Etc etc. In short, the "last return" wins when no other is specified.

And then you can even check the number of invocations:

verify(mutator, times(3)).randomSynapseWeightChange(); 
Sign up to request clarification or add additional context in comments.

5 Comments

If you need help with it, don't hesitate! I'm a heavy user of it and know it quite well
Thanks will do. I suspect I've got a steep learning curve ahead of me though I'm pleased to see it plays nicely with JUnit which I already know very well.
Your suspiscion is mispaced, mockito is actually pretty easy to learn ;) It is, imho, in large part due to the fact that the code you write is no less than "human readable"; this is a pretty nice feature of any library you want to use, and mockito provides just that, as does assertj for assertions!
Could I take you up on your offer to help with Mockito? I've started using it but something has me stumped and I can't find a previous question that matches it
Well, just ask another question then

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.