The Unit Test fails sometime due to bad design - c#

Below are the two classes Sensor and Indicator which contains some business logic and a Unit Test. The unit test fails sometimes due to a bad design. I tried to fix the implementation and correct the unit test but I am still getting problem. I need your help to fix the implementation.
public class Sensor
{
const double Offset = 16;
public double GetFuelAmountValue()
{
double value;
SampleAmount(out value);
return Offset + value;
}
private static void SampleAmount(out double fuelTelemetryValue)
{
Random basicRandomNumbersGenerator = new Random();
fuelTelemetryValue = basicRandomNumbersGenerator.Next(0, 25);
}
}
public class Indicator
{
private const double LowFuelTreshold = 7;
private const double HighFuelTreshold = 21;
Sensor _sensor = new Sensor();
bool _alarm = false;
private long _alarmCount = 0;
public void Check()
{
double LitersOfFuelValue = _sensor.GetFuelAmountValue();
if (LitersOfFuelValue < LowFuelTreshold || HighFuelTreshold < LitersOfFuelValue)
{
_alarm = true;
_alarmCount += 1;
}
}
public bool Alarm
{
get { return _alarm; }
}
}
This is the test
[TestClass]
public class FuelIndicatorTest
{
[TestMethod]
public void Foo()
{
Indicator indicator = new Indicator();
indicator.Check();
Assert.AreEqual(false, indicator.Alarm);
}
}

I understand that this is a simplified code - not production one. Here one way how to mock random generated number FuelTelementryNumber and pass it in test via constructor.
public class Sensor
{
const double Offset = 16;
Func<double> _getFuelTelemetry;
public Sensor(Func<double> getFuelTelemetry)
{
_getFuelTelemetry = getFuelTelemetry;
}
public Sensor()
: this(SampleAmount)
{
}
public double GetFuelAmountValue()
{
double value = _getFuelTelemetry();
return Offset + value;
}
private static double SampleAmount()
{
Random basicRandomNumbersGenerator = new Random();
return basicRandomNumbersGenerator.Next(0, 25);
}
}
public class Indicator
{
private const double LowFuelTreshold = 7;
private const double HighFuelTreshold = 21;
Sensor _sensor;
public Indicator(Sensor sensor)
{
_sensor = sensor;
}
public Indicator() : this(new Sensor())
{
}
bool _alarm = false;
private long _alarmCount = 0;
public void Check()
{
double LitersOfFuelValue = _sensor.GetFuelAmountValue();
if (LitersOfFuelValue < LowFuelTreshold || HighFuelTreshold < LitersOfFuelValue)
{
_alarm = true;
_alarmCount += 1;
}
}
public bool Alarm
{
get { return _alarm; }
}
}
[TestClass]
public class FuelIndicatorTest
{
[TestMethod]
public void Foo()
{
Indicator indicator = new Indicator(new Sensor(() => {return 25;}));
indicator.Check();
Assert.AreEqual(true, indicator.Alarm);
}
}

Related

How to generalize a property pattern

I have classes that has multiple properties which have well-defined name and function but have the same implementation. For example:
class Stats
{
private int attack;
public int Attack
{
get =>
HasBuff ? attack + 1 : attack;
set
{
if (value < 1 || value > 10)
throw new ArgumentOutOfRangeException("Invalid value");
attack = value;
}
}
public int Defense {...}
public int Speed {...}
}
Where Defense and Speed are to be implemented just like Attack . How can I generalize this structure to avoid redundancy and make changes easier?
Make another class to generalize stats:
public class Stat
{
public bool HasBuff { get; set; }
private int _stat;
public int Score
{
get => HasBuff ? _stat + 1 : _stat;
set => _stat = value;
}
}
Then just use that for each of your skills:
public class CombatStats
{
public Stat Attack { get; } = new Stat();
public Stat Defense { get; } = new Stat();
public Stat Speed { get; } = new Stat();
}
Calling code would look like this:
var ninja = new Ninja();
ninja.skills = new CombatStats();
var attackStrength = ninja.skills.Attack.Score;
As further improvement, implicit operators can be used to avoid object creation and call to Score:
public class Stat
{
...
public static implicit operator int(Stat stat)
{
return stat.Score;
}
public static implicit operator Stat(int value)
{
return new Stat()
{
Score = value
};
}
}
This makes the change transparent to client code written w.r.t. to the example in the question:
ninja.skills = new CombatStats(){
Attack = 5,
Defense = 2
}
int attack = ninja.skills.Attack;
One approach to consider:
class Stats
{
// other existing code here
private int defense;
public int Defense
{
get
{
return GetValue(defense);
}
set
{
SetValue(value, ref defense);
}
}
private int GetValue(int value)
{
return HasBuff ? value + 1 : value;
}
private void SetValue(int value, ref int target)
{
if (value < 1 || value > 10)
throw new ArgumentOutOfRangeException("Invalid value");
target = value;
}
}
Attack etc will now be basically the same as Defence but passing in attack rather than defense to GetValue and SetValue.
I would go with composition
Stat:
public class Stats
{
private readonly StatProperty _defense;
private readonly StatProperty _attack;
private readonly StatProperty _speed;
public Stats()
{
_defense = new StatProperty(this);
_attack = new StatProperty(this);
_speed = new StatProperty(this);
}
public int Defense
{
get => _defense.Value;
set => _defense.Value = value;
}
public int Attack
{
get => _attack.Value;
set => _attack.Value = value;
}
public int Speed
{
get => _speed.Value;
set => _speed.Value = value;
}
public bool HasBuff { get; set; }
}
StatProperty:
public class StatProperty
{
public Stats Stats { get; }
public StatProperty(Stats stats)
{
Stats = stats;
}
private int _value = 1;
public int Value
{
get => Stats.HasBuff ? _value + 1 : _value;
set
{
if (value < 1 || value > 10)
throw new ArgumentOutOfRangeException("Invalid value");
_value = value;
}
}
}
I would need more details to know if it is the best option.
you also could make StatProperty as internal if don't want to show it outside of your library or nested private class if you want to use this just on the class Stats

How to access array members that are of an interface type c#

I am a little lost here.
Basically, I need to access an array item, a string and display it. Here is the code.
namespace Test3_2_Practice
{
public partial class InterfaceImplementation : Form
{
//Array
ICombatant[] combatants = new ICombatant[2];
public InterfaceImplementation()
{
InitializeComponent();
}
private void btnTest_Click(object sender, EventArgs e)
{
combatants[0] = new PlayerCharacter ("Conan" , 500);
combatants[1] = new MonsterCharacter ("Bob" , 5);
combatants[2] = new MonsterCharacter ("Snake" , 15);
string output = "Fighters" + Environment.NewLine;
for (var i = 0; i < combatants.Length; i++)
{
var character = combatants[i];
output += "Character:" + combatants[i].
}
}
}
}
So I have my array, combatants composed of two types of instances. I want to access the name, "Conan" and add it to a string for output. How do I go about doing that? Here is the rest of the code if that helps. Thanks!
namespace Test3_2_Practice
{
//Interface
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
}
class PlayerCharacter : ICombatant
{
private string characterName;
private int currentHealth;
private int maxHealth;
public string CharacterName
{
get { return characterName; }
set { characterName = value; }
}
public int CurrentHealth
{
get { return currentHealth; }
set { currentHealth = value; }
}
public int MaxHealth
{
get { return maxHealth; }
set { maxHealth = value; }
}
public PlayerCharacter(string characterName, int maxHealth)
{
CharacterName = characterName;
CurrentHealth = MaxHealth = maxHealth;
}
//Damage Class
public int TakeDamage(int damageAmount)
{
if (damageAmount > currentHealth)
{
damageAmount = currentHealth;
return damageAmount;
}
else
{
currentHealth = currentHealth - damageAmount;
return damageAmount;
}
}
//Health Class
public string GetHealthDisplay()
{
return ("Health " + CurrentHealth.ToString() + "/" + MaxHealth).ToString();
}
}
class MonsterCharacter : ICombatant
{
private string monsterName;
private int health;
public string MonsterName
{
get { return monsterName; }
set { monsterName = value; }
}
public int Health
{
get { return health; }
set { health = value; }
}
public MonsterCharacter(string monsterName, int health)
{
MonsterName = monsterName;
Health = health;
}
//Damage Class
public int TakeDamage(int damageAmount)
{
if(damageAmount > health)
{
damageAmount = health;
return damageAmount;
}
else
{
health = health - damageAmount;
return damageAmount;
}
}
//Health Class
public string GetHealthDisplay()
{
return "Health " + Health;
}
}
}
Actually, since name is common to all implementer of interface that Name property should be included to interface itself like
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
public string CharacterName
{
get;
set;
}
}
In your current scenario, you will have to cast it specific concrete type before accessing it
var character = combatants[i];
if(character is PlayerCharacter)
output += "Character:" + ((PlayerCharacter)character).CharacterName;
It's better to make a good use of your interface. Create a new method in your interface:
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
string GetCombatantName(); // added this
}
Then implement in both classes which implements it:
class PlayerCharacter : ICombatant
{
// ... a lot of code ...
public string GetCombatantName()
{
return String.Format("Character: {0}", this.CharacterName);
}
}
class MonsterCharacter: ICombatant
{
// ... a lot of code ...
public string GetCombatantName()
{
return String.Format("Monster: {0}", this.MonsterName);
}
}
And use it like this:
private void btnTest_Click(object sender, EventArgs e)
{
combatants[0] = new PlayerCharacter("Conan", 500);
combatants[1] = new MonsterCharacter("Bob", 5);
combatants[2] = new MonsterCharacter("Snake", 15);
string output = "Fighters" + Environment.NewLine;
foreach (var combatant in combatants)
{
output += combatant.GetCombatantName();
}
}
So if one day you get ten distinct types of ICombatant (like AnimalCharacter, VirusCharacter), you don't have to nest a lot of ifs to check and cast types to get the proper property.
Interfaces are meant exactly to avoid this kind of stuff, hiding the implementation details.

C# - Getter and Setter dosen't keep the value

Here is my code:
private int pressedMain = 1;
public int PressedMain
{
get
{
return pressedMain;
}
set
{
pressedMain = value;
}
}
And then I change the value of pressedMain:
pw.PressedMain++;
But in the following class my value is one, why and how can I slove this problem?
Example invoke, console prints 2 here
public class Foo
{
private int pressedMain = 1;
public int PressedMain
{
get
{
return pressedMain;
}
set
{
pressedMain = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
foo.PressedMain++;
Console.WriteLine(foo.PressedMain);
Debugger.Break();
}
}

C# struct treated like a Reference

I have struct called KinectBody and i assign an object of this type which is in a class called BodyContributor to a field in a class called KinectSystemComponent. Now every time the field in the BodyContributor changes, the field in my KinectSystemComponent changes too just like it was a reference type. How does that happen. Below are the involved classes:
using System.Collections.Generic;
namespace Alpaca.Systems.Kinect
{
public class KinectSystemComponent : KinectComponent, Alpaca.Systems.Events.IEventHandler<UserTrackingEvent>
{
private static Dictionary<ulong, KinectBody> assignedBodies = new Dictionary<ulong, KinectBody>();
BodyContributor contributor;
public static bool useSystemComponents = true;
public static bool IsBodyAlreadyAssigned(KinectBody body)
{
return assignedBodies.ContainsKey(body.trackingID);
}
public override void Initialize()
{
contributor = BodySource.Instance.contributor;
this.ComponentType = ComponentType.SystemComponent;
}
public override void OnUpdate()
{
//if(useSystemComponents)
//{
// if(!Body.isTracked)
// {
// KinectBody[] bodies = contributor.GetBodies();
// for(int i = 0; i < bodies.Length; i++)
// {
// KinectBody currentBody = bodies[i];
// if(currentBody.isTracked)
// {
// if(!IsBodyAlreadyAssigned(currentBody))
// {
// this.Body = currentBody;
// }
// }
// }
// }
// else
// {
// Body = contributor.GetBodyByID(Body.trackingID);
// }
//}
//else if(Body.isTracked)
//{
// Body = new KinectBody();
//}
}
public void HandleEvent(UserTrackingEvent #event)
{
Body = contributor.GetBodyByID(#event.id);
}
}
}
using System;
using Alpaca.Systems;
namespace Alpaca.Systems.Kinect
{
public abstract class KinectComponent : AlpacaComponent
{
private KinectBody body;
public KinectBody Body
{
get
{
return body;
}
protected set
{
body = value;
}
}
}
}
using System.Collections.Generic;
using UnityEngine;
using Windows.Kinect;
using Alpaca.Utility;
namespace Alpaca.Systems.Kinect
{
public struct KinectBody
{
public Dictionary<JointType, KinectJoint> joints;
Dictionary<JointType, Windows.Kinect.Joint> rawJoints;
public bool isTracked;
public ulong trackingID;
public Vector3 position;
public Vector3 hipsDirection;
public Vector3 shouldersDirection;
public float bodyTurnAngle;
public Vector3 leftArmDirection;
public Vector3 rightArmDirection;
public void Init()
{
joints = new Dictionary<JointType, KinectJoint>(25, new JointTypeComparer());
}
public void RefineBody(Body body)
{
this.rawJoints = body.Joints;
for(int i = 0; i < 25; i++)
{
joints[KinectHelper.GetJointAtIndex(i)] = new KinectJoint(rawJoints[KinectHelper.GetJointAtIndex(i)]);
}
position = joints[JointType.SpineMid].position;
isTracked = body.IsTracked;
trackingID = body.TrackingId;
hipsDirection = Vector3.zero;
shouldersDirection = Vector3.zero;
bodyTurnAngle = 0;
leftArmDirection = Vector3.zero;
rightArmDirection = Vector3.zero;
}
public void ModifyJoint(JointType type, KinectJoint joint)
{
joints[type] = joint;
}
}
public class KinectBodyComparer : IEqualityComparer<KinectBody>
{
bool System.Collections.Generic.IEqualityComparer<KinectBody>.Equals(KinectBody x, KinectBody y)
{
return x.trackingID == y.trackingID;
}
int System.Collections.Generic.IEqualityComparer<KinectBody>.GetHashCode(KinectBody obj)
{
return unchecked((int) (obj.trackingID % 1000));
}
}
}
namespace Alpaca.Systems.Kinect
{
public abstract class BodyContributor
{
protected KinectBody[] bodies = new KinectBody[6];
private BodyRefiner refiner;
protected KinectBody emptyBody;
public BodyContributor(BodyRefiner refiner)
{
this.refiner = refiner;
emptyBody = new KinectBody();
}
public void Update()
{
this.bodies = refiner.GetBodies();
UpdateBodies();
}
protected abstract void UpdateBodies();
public KinectBody GetBodyByID(ulong id)
{
for(int i = 0; i < bodies.Length; i++)
{
KinectBody curBody = bodies[i];
if(curBody.trackingID == id)
{
return curBody;
}
}
return emptyBody;
}
public KinectBody[] GetBodies()
{
return bodies;
}
}
}
As Carsten has pointed out, KinectComponent is a class, a reference type.
KinectBody may be a value type, but it contains reference types (Dictionarys), which I suspect will lead to behaviour you don't expect.
Your struct also is large and mutable, which breaks these useful design guidelines

How to acces a method from another instance that was given in the constructor?

So I have the following set-up.
A sensor that detects the temperature of a room a controller then checks if it is below or above a set temperature and if it is below it starts a heater.
Now how do I get the method GetCurTemp() to get the temperature I have set?
public class TempSensor
{
public int Temp { get; set; }
}
public class Control
{
private int threshold;
public Control(TempSensor t, Heater h, int thr)
{
threshold = thr;
}
public void SetThreshold(int thr)
{
threshold = thr;
}
public int GetThreshold()
{
return threshold;
}
public int GetCurTemp()
{
return ???;
}
}
class Test
{
static void Main(string[] args)
{
var tempSensor = new TempSensor();
var heater = new Heater();
var uut = new Control(tempSensor, heater, 25);
Console.WriteLine("Set the current temperatur");
int n= int.Parse(Console.ReadLine());
tempSensor.Temp = n;
}
}
You need to keep a reference to the TempSensor in your Control class. Then you can access the temperature from that reference.
public class Control
{
private int threshold;
private TempSensor sensor;
public Control(TempSensor t, Heater h, int thr)
{
threshold = thr;
sensor = t;
}
public void SetThreshold(int thr)
{
threshold = thr;
}
public int GetThreshold()
{
return threshold;
}
public int GetCurTemp()
{
return sensor.Temp;
}
}
You aren't doing anything with the TempSensor object you're passing into the Control constructor. You should set up a field like sensorTemp in your Control class to hold this value.
public class Control
{
private int threshold;
private int sensorTemp;
public Control(TempSensor t, Heater h, int thr)
{
threshold = thr;
sensorTemp = t.Temp;
}
public void SetThreshold(int thr)
{
threshold = thr;
}
public int GetThreshold()
{
return threshold;
}
public int GetCurTemp()
{
return sensorTemp;
}
}

Categories

Resources