Mockk android.graphics.Rect - unit-testing

I'm trying to mock the top, left, bottom, right properties inside android.graphics.Rect but I always get the error:
io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
I've tried several techniques, but they all produce the above error message:
val rectMock = mockk<Rect>()
every { rectMock.left } returns 123
every { rectMock.left } propertyType Int::class returns 123
every { rectMock getProperty "left" } returns 123

My mistake was that top, left, bottom and right are variables, not methods so they cannot be mocked
public final class Rect implements Parcelable {
public int left;
public int top;
public int right;
public int bottom;
...
As #Augusto pointed out I shouldn't have mocked Rect anyway, and if I hadn't tried I would have been fine!
val rect = Rect()
rect.left = 123

Related

Simple issue - How to access a variable from a 'class' inside a separate 'struct'?

I am new to C++/JUCE. I have been working to get a basic synth running and just testing some things out to learn the ropes.
It’s working fine already. But I’m still just learning my way around C++/JUCE and how to declare or access classes/objects/variables.
I’m trying to make a modification to something that I’m stuck with.
I have the following (just excerpts to demonstrate)…
This is where the synthesizer level is set:
struct SineWaveVoice : public SynthesiserVoice
{
SineWaveVoice() {}
bool canPlaySound (SynthesiserSound* sound) override
{
return dynamic_cast<SineWaveSound*> (sound) != nullptr;
}
void startNote (int midiNoteNumber, float velocity,
SynthesiserSound*, int /*currentPitchWheelPosition*/) override
{
currentAngle = 0.0;
level = velocity * 0.15;
tailOff = 0.0;
Ie. Level is set by velocity * 0.15.
In my test set up, I already have a level knob defined under MainContentComponent like this:
class MainContentComponent : public AudioAppComponent,
private Timer
{
public:
MainContentComponent()
: synthAudioSource(keyboardState),
keyboardComponent(keyboardState, MidiKeyboardComponent::horizontalKeyboard)
{
LabeledSlider* control = new LabeledSlider("Frequency");
control->slider.setRange(20.0, 20000.0);
control->slider.setSkewFactorFromMidPoint(500.0);
control->slider.setNumDecimalPlacesToDisplay(1);
control->slider.setValue(currentFrequency, dontSendNotification);
control->slider.onValueChange = [this] { targetFrequency = frequency.slider.getValue(); };
control->slider.setTextBoxStyle(Slider::TextBoxBelow, false, 100, 20);
control->slider.setRange(50.0, 5000.0);
control->slider.setSkewFactorFromMidPoint(500.0);
control->slider.setNumDecimalPlacesToDisplay(1);
addAndMakeVisible(knobs.add(control));
control = new LabeledSlider("Level");
control->slider.setRange(0.0, 1.0);
control->slider.onValueChange = [this] { targetLevel = (float)level.slider.getValue(); };
addAndMakeVisible(knobs.add(control));
....
private:
{
float currentLevel = 0.1f, targetLevel = 0.1f;
LabeledSlider level{ "Level" };
So let’s say I want to use this level slider variable “targetLevel” to be multiplied by the velocity in the “struct” above instead of 0.15.
What do I need to type up there to be able to access and use “targetLevel”? I tried multiple things but I can’t quite figure it out.
Thanks
I am assuming that your SineWaveVoice lies within your SynthAudioSource class and that the voice is a part of a Synthesizer object. To access anything within your SineWaveVoice struct from MainContentComponent you need to expose this somehow via the SynthAudioSource. So my suggestion is that in your SynthAudioSource add a method like this:
void setLevel(double lvl)
{
for (auto i=0; i<synth.getNumVoices(); i++)
{
SineWaveVoice *v = dynamic_cast<SineWaveVoice *>(synth.getVoice(i));
v->level = lvl * v->velocity;
}
}
Then to access this in your MainContentComponent you just do this:
control->slider.onValueChange = [this] {
targetLevel = (float)level.slider.getValue();
synthAudioSource.setLevel(targetLevel);
};
However, notice that this value will be overwritten every time you get a new startNote event. So you should probably store a copy of target level in your SineWaveVoice and multiply with that rather than 0.15.

How to stop MsTest tests execution after *n* failed tests

I want to run unit tests via MS Test (from windows console) in a way that I can stop/kill the test execution whenever the failed tests count exceeds certain threshold value.
For my use case there is no point to keep running tests when certain percentage of the tests already failed.
I can only think in creating a new console app to wrap the mstest.exe execution, so I can parse the standard output in real-time,
and eventually kill the process, for example:
var pi = new ProcessStartInfo()
{
FileName = MS_TEST,
UseShellExecute = false,
RedirectStandardOutput = true,
Arguments = MS_TEST_ARGS
};
int passed = 0; int failed = 0;
using (var process = Process.Start(pi))
{
while (!process.StandardOutput.EndOfStream)
{
string line = process.StandardOutput.ReadLine();
if (line.Contains("Passed"))
passed++;
if (line.Contains("Failed"))
failed++;
if (failed >= THRESHOLD)
{
process.Kill();
break;
}
}
}
Can anyone suggest a better way for doing this? I don't think this is natively supported by MsTest.
PowerShell seems to be an option, but the stdout redirect is not trivial.
Update
As a note, I cannot modify the test code, I need this to be done without modifying the tests code in any way.
Create a BaseTestClass which contains a method responsible for killing the process that runs the tests.
using System.Diagnostics;
namespace UnitTestProject1
{
public class BaseTestClass
{
private readonly int _threshold = 1;
private static int _failedTests;
protected void IncrementFailedTests()
{
if (++_failedTests >= _threshold)
Process.GetCurrentProcess().Kill();
}
}
}
Your must inherit all your test classes from BaseTestClass and use the [TestCleanup] attribute. The TestCleanup() method is evaluated when a test defined in the DemoTests class has finished running. Is in that method where we evaluate the output of the test that has just finished. If it failed, we kill the process responsible for running the tests.
In the following example we have defined three tests. The second test, Test_Substracting_Operation(), is intended to fail intentionally, so the third test will never be run.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject1
{
[TestClass]
public class DemoTests : BaseTestClass
{
public TestContext TestContext { get; set; }
[TestCleanup]
public void TestCleanup()
{
if (TestContext.CurrentTestOutcome == UnitTestOutcome.Failed)
{
IncrementFailedTests();
}
}
[TestMethod]
public void Test_Adding_Operation()
{
// Arrange
int x = 1;
int y = 2;
// Act
int result = x + y;
// Assert
Assert.AreEqual(3, result);
}
[TestMethod]
public void Test_Substracting_Operation()
{
// Arrange
int x = 1;
int y = 2;
// Act
int result = x - y;
// Assert
Assert.AreEqual(100, result);
}
[TestMethod]
public void Test_Multiplication_Operation()
{
// Arrange
int x = 1;
int y = 2;
// Act
int result = x * y;
// Assert
Assert.AreEqual(2, result);
}
}
}

gmock gtest how to setup the mock

Please consider the below code sample
NodeInterface * pPreNode = NULL;
NodeInterface * pChild = NULL;
for (uint16_t Index = 0; Index < Children.size(); ++Index)
{
pChild = Children[Index];
if (pPreNode == NULL)
{
pChild->SetPrevious(pChild);
pChild->SetNext(pChild);
}
else
{
pChild->SetNext(pPreNode->GetNext());
pChild->SetPrevious(pPreNode);
pPreNode->GetNext()->SetPrevious(pChild);
pPreNode->SetNext(pChild);
}
pPreNode = pChild;
}
To test this lines how to setup the mock exactly?
Children is a vector of Nodes and we are passing Mocked objects.
EXPECT_CALL(Obj, GetNode()).WillOnce(Invoke(this, &GetANewNode));
and the GetANewNode will provide new MockedNode
MockedNode * GetANewNode()
{
MockedNode * pMockedNode = new MockedNode();
return pMockedNode;
}
How to provide exact nodes for each Next(), Previous() calls?
EXPECT_CALL(*pMockedNode, SetNext(_));
EXPECT_CALL(*pMockedNode, SetPrevious(_));
EXPECT_CALL(*pMockedNode, GetNext());
EXPECT_CALL(*pMockedNode, GetPrevious());
Simple solution is to have all mocked nodes predefined before test case. And use Sequence/InSequence to be sure that everything happens in proper order.
class ObjTest : public ::testing::Test
{
protected:
const std::size_t N = ...; // I do not know how many do you need
std::vector<MockedNode> mockedNode;
std::vector<Node*> children;
Sequence s;
.... Obj; // I am not sure what is Obj in your question
ObjTest () : mockedNode(N)
{}
void SetUp() override
{
// initial setup
EXPECT_CALL(Obj, GetNode()).WillOnce(Return(&mockedNode.front())).InSequence(s);
}
};
Having such test class with initial setup - you can create test cases testing various scenarios that happen after initial sequence:
TEST_F(ObjTest, shouldLinkOneNodeToItself)
{
std::vector<Node*> children { &mockedNode[0] };
EXPECT_CALL(mockedNode[0], SetNext(&mockedNode[0])).InSequence(s);
EXPECT_CALL(mockedNode[0], SetPrevious(&mockedNode[0])).InSequence(s);
Obj.testedFunction(children); // you have not provided your tested function name...
}
And very similar test case for two children:
TEST_F(ObjTest, shouldLinkTwoNodesToEachOther)
{
std::vector<Node*> children { &mockedNode[0], &&mockedNode[1] };
// first interation
EXPECT_CALL(mockedNode[0], SetNext(&mockedNode[0])).InSequence(s);
EXPECT_CALL(mockedNode[0], SetPrevious(&mockedNode[0])).InSequence(s);
// second iteration
EXPECT_CALL(mockedNode[0], GetNext()).WillOnce(Return(&mockedNode[0])).InSequence(s);
EXPECT_CALL(mockedNode[1], SetNext(&mockedNode[0])).InSequence(s);
EXPECT_CALL(mockedNode[1], SetPrevious(&mockedNode[0])).InSequence(s);
// etc...
Obj.testedFunction(children);
}

Cannot to delete the GameObject

I put the all GameObjects in scene under a list. the following is function used in the shelf.cs to delete the gameobjects. I assign the function to a button, so that it takes input value and find which Gameobject has lesser value than input. Then delete. The problem is whenever I click the button in the game preview, it won't delete the gameobjects. There are no warnings. I debug whether it receives all input, and it did. just not deleting the GameObjects.
Why?
public void Process(){
int user_apple,user_lemon,user_watermelon;
user_apple = int.Parse (input_apple.text);
user_lemon = int.Parse (input_lemon.text);
user_watermelon = int.Parse (input_watermelon.text);
Debug.Log (user_apple+" "+user_lemon+" "+user_watermelon);
for(int i = players.Count - 1; i >= 0; i--)
{ if(players[i].name == "Lemon")
{
if(players[i].GetComponent<Apple>().weight <= user_apple)
{ Debug.Log ("wat u want");
Destroy(players[i]);
}players.RemoveAt(i);
}
}
}
if i were to put it like this,
public void Process(){
int user_apple,user_lemon,user_watermelon;
user_apple = int.Parse (input_apple.text);
user_lemon = int.Parse (input_lemon.text);
user_watermelon = int.Parse (input_watermelon.text);
Debug.Log (user_apple+" "+user_lemon+" "+user_watermelon);
if(players[2].GetComponent<Lemon>().weight <= user_apple)
{ Destroy(players[2]);
players.RemoveAt(2);
}
}
it will have errors like below
FormatException: Input string was not in the correct format
System.Int32.Parse (System.String s) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Int32.cs:629)
Basket.Process () (at Assets/scripts/Basket.cs:77)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:110)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:575)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:717)
UnityEngine.Events.UnityEvent.Invoke () (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/UI/Core/Button.cs:36)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/UI/Core/Button.cs:45)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()
This may not be the right solution try calling a co-routine from the Process Function and yield the loop so it runs everyframe.
Just to recap what Joe Blow said: there is no reason why this for loop should not work since it is totally independant of frames/time.
This little example works perfectly fine:
The script ScriptHolder is assigned to an empty gameobject (see screen below) and looks like this:
using UnityEngine;
using System.Collections.Generic;
public class ScriptHolder: MonoBehaviour
{
public List<GameObject> theGameObjects;
public void TheButtonFunction(int weight)
{
for(int i = theGameObjects.Count - 1; i >= 0; i--)
{
if(theGameObjects[i].GetComponent<TheObject>().objectWeight <= weight)
{
Destroy(theGameObjects[i]);
theGameObjects.RemoveAt(i);
}
}
}
}
All gameobjects were dragged into the public list.
The script for the gameobjects looks like this:
using UnityEngine;
using System.Collections;
public class TheObject : MonoBehaviour
{
public string objectName = "";
public int objectWeight = 0;
}
All GameObject_A are named A and have a weight of 10 (done in the inspector), GameObject_B are B with a weight of 15 and GameObject_C are C with a weight of 20. Columns are A to C from left to right.
The button calls the function from above with a value of 15.
When I click the button, the left and the middle columns of gameobjects are deleted from the scene and from the list - no problem whatsoever.

Using the method of an object in an ArrayList in an if statement

I'm trying to use a method from an object in an ArrayList, that's a parameter of a method... I'm not sure what the syntax is. It's the condition of the if where the problem is. It's not supposed to be Ship, but what else? .getSize() is a method in the Ship class. Or maybe this solution is totally off?
public void deployShips(char[][] board, ArrayList<Ship> fleet, int x, int y) {
if (Ship.getSize() == 5) {
int[] coordinate = coordinate(x, y);
board[coordinate[0]][coordinate[1]] = '+';
}
}
If i have understand what you need the code should be this:
n = the index postion of the object you need to call
fleet.get(n).theMethodYouNeed();
or if you need to check the entire list:
for(Ship ship: fleet){
if (ship.getSize() == 5) {
int[] coordinate = coordinate(x, y);
board[coordinate[0]][coordinate[1]] = '+';
}
}