Moq SetupSet on property - moq

i am trying to learn to use Moq (4) to test the C# code below. I was hoping that by setting
mockTimer.SetupSet(m => m.Interval = It.IsInRange(
interval - shorter, interval + longer, Range.Inclusive));
before calling the method which assigns the interval property a value (ageService.AddParticipant method), the test would throw when an incorrect value was assigned. However, even when a value well outside the specified range is assigned to the Interval property within the AddParticipant method, the test passes. I also find timer.Interval has a value of 0 after executing the AddParticipant method, even though I can see this property being assigned a non-zero value when stepping through the AddParticipant method.
[TestMethod]
public void TestAgeUpdatingStartOnAdd()
{
var mockTimer = new Mock<IDispatcherTimer>();
mockTimer.SetupProperty(m => m.Interval);
mockTimer.Setup(m => m.Start());
mockTimer.Setup(m => m.Stop());
IDispatcherTimer timer = mockTimer.Object;
var ageService = new AgeUpdatingService(timer);
TimeSpan interval = TimeSpan.FromMinutes(10);
TimeSpan tolerance = TimeSpan.FromMilliseconds(100)
mockTimer.SetupSet(m => m.Interval = It.IsInRange(
interval - tolerance, interval + tolerance, Range.Inclusive));
ageService.AddParticipant(new Participant{ DOB = DateTime.Now + interval });
What am I doing wrong? Am I missing the point of the SetupSet method all together (and therefore should just stick to examining the properties on the timer object after executing the function, which seemed to work prior to placing the SetupSet method in the code)? If so, could you please explain what SetupSet exists for. Thank you.

Since you're creating your mock with new Mock<IDispatcherTimer>(), it defaults to Loose mock behavior. This means that the mock object will not complain when it is used in a way that was not specified via a Setup method. Using the constructor overload that accepts a MockBehavior enumeration and specifying Strict will make the code behave like you'd expect. It looks like that's how you're expecting to use it judging by the Setup calls; they would be unnecessary if you were using loose mocks.
Alternatively you can keep the loose mock and change the SetupSet for the Interval to be a VerifySet after you expect it to be set. I.e.:
var ageService = new AgeUpdatingService(timer);
TimeSpan interval = TimeSpan.FromMinutes(10);
TimeSpan tolerance = TimeSpan.FromMilliseconds(100)
ageService.AddParticipant(new Participant{ DOB = DateTime.Now + interval });
mockTimer.VerifySet(m => m.Interval = It.IsInRange(
interval - tolerance, interval + tolerance, Range.Inclusive));
This is like a test assertion, meaning if a set of the Interval property never happened when this is invoked, it would throw a MoqException and fail the test.

SetupSet can be used to setup a property setter - it is fairly unusual to need this, as arguments passed to Set typically don't need to be captured, as the calls to the Setter can be verified with a VerifySet after the "Act" step.
Here's a way to achieve what you want:
var mockTimer = new Mock<ITimer>();
// Simulate the actions of the Sut with the Mock
mockTimer.Object.Interval = 6;
mockTimer.Object.Interval = 7;
mockTimer.Object.Interval = 999;
// Ensure the mock was called in-band
mockTimer.VerifySet(m => m.Interval = It.IsInRange(5, 10, Range.Inclusive),
Times.Exactly(2));
// Ensure the mock was not called out of band
mockTimer.VerifySet(m => m.Interval = It.Is<int>(i => i < 5 || i > 10),
Times.Never);
Another, less elegant approach would be to use SetupSet to detect invalid invocations directly:
mockTimer.SetupSet(m => m.Interval = It.Is<int>(i => i < 5 || i > 10))
.Throws(new ArgumentOutOfRangeException());

Related

Cannot get Realm result for objects filtered by the latest (nsdate) value of a property of a collection property swift (the example is clearer)

I Have the following model
class Process: Object {
#objc dynamic var processID:Int = 1
let steps = List<Step>()
}
class Step: Object {
#objc private dynamic var stepCode: Int = 0
#objc dynamic var stepDateUTC: Date? = nil
var stepType: ProcessStepType {
get {
return ProcessStepType(rawValue: stepCode) ?? .created
}
set {
stepCode = newValue.rawValue
}
}
}
enum ProcessStepType: Int { // to review - real value
case created = 0
case scheduled = 1
case processing = 2
case paused = 3
case finished = 4
}
A process can start, processing , paused , resume (to be in step processing again), pause , resume again,etc. the current step is the one with the latest stepDateUTC
I am trying to get all Processes, having for last step ,a step of stepType processing "processing ", ie. where for the last stepDate, stepCode is 2 .
I came with the following predicate... which doesn't work. Any idea of the right perform to perform such query ?
my best trial is the one. Is it possible to get to this result via one realm query .
let processes = realm.objects(Process.self).filter(NSPredicate(format: "ANY steps.stepCode = 2 AND NOT (ANY steps.stepCode = 4)")
let ongoingprocesses = processes.filter(){$0.steps.sorted(byKeyPath: "stepDateUTC", ascending: false).first!.stepType == .processing}
what I hoped would work
NSPredicate(format: "steps[LAST].stepCode = \(TicketStepType.processing.rawValue)")
I understand [LAST] is not supported by realm (as per the cheatsheet). but is there anyway around I could achieve my goal through a realm query?
There are a few ways to approach this and it doesn't appear the date property is relevant because lists are stored in sequential order (as long as they are not altered), so the last element in the List was added last.
This first piece of code will filter for processes where the last element is 'processing'. I coded this long-handed so the flow is more understandable.
let results = realm.objects(Process.self).filter { p in
let lastIndex = p.steps.count - 1
let step = p.steps[lastIndex]
let type = step.stepType
if type == .processing {
return true
}
return false
}
Note that Realm objects are lazily loaded - which means thousands of objects have a low memory impact. By filtering using Swift, the objects are filtered in memory so the impact is more significant.
The second piece of code is what I would suggest as it makes filtering much simpler, but would require a slight change to the Process model.
class Process: Object {
#objc dynamic var processID:Int = 1
let stepHistory = List<Step>() //RENAMED: the history of the steps
#objc dynamic var name = ""
//ADDED: new property tracks current step
#objc dynamic var current_step = ProcessStepType.created.index
}
My thought here is that the Process model keeps a 'history' of steps that have occurred so far, and then what the current_step is.
I also modified the ProcessStepType enum to make it more filterable friendly.
enum ProcessStepType: Int { // to review - real value
case created = 0
case scheduled = 1
case processing = 2
case paused = 3
case finished = 4
//this is used when filtering
var index: Int {
switch self {
case .created:
return 0
case .scheduled:
return 1
case .processing:
return 2
case .paused:
return 3
case .finished:
return 4
}
}
}
Then to return all processes where the last step in the list is 'processing' here's the filter
let results2 = realm.objects(Process.self).filter("current_step == %#", ProcessStepType.processing.index)
The final thought is to add some code to the Process model so when a step is added to the list, the current_step var is also updated. Coding that is left to the OP.

Convert datetime to other runtimetype in flutter app

I'm trying to convert a DateTime runtimetype value to Expression<DateTime, DateTimeType>. I've been trying to achieve this for almost three days now. I have tried different approaches but non is working.
The reason I want to achieve this is because moor_flutter library in some cases uses and accepts the library's custom runtimetypes on methods and and the parameter values on those methods.
Below is the sample code;
final DateTime dateToday = new DateTime.now(); // convert DateTime to Expression<DateTime, DateTimeType>
var dateWithNewRuntimetype; // assign the converted value to this variable
I thought I fixed this issue by adding as as Expression<DateTime, DateTimeType> to the value of dateWithNewRuntimetype variable value but no this is not the solution either.
The solution will work on the code below
Stream<List> getLoansWithTomorrowDueDate(int dayInFuture) {
return (select(loans)
..where((l) => l.due_date.isBetween(
dateToday, // it should be Expression<DateTime, DateTimeType> not DateTIme
futureDate, // it should be Expression<DateTime, DateTimeType> not DateTIme)))
.watch();
}
If you want me to provide more info on this I will do so.
Thank you, so much Love.
The isBetween is compared withSqlType.
You must use isBetweenValues.
/// Defines extension functions to express comparisons in sql
extension ComparableExpr<DT, ST extends ComparableType<DT>>
on Expression<DT, ST> {
Expression<bool, BoolType> isBetween(
Expression<DT, ST> lower, Expression<DT, ST> higher,
{bool not = false});
Expression<bool, BoolType> isBetweenValues(DT lower, DT higher,
{bool not = false});
}

Moq: How to ensure Verify() reports on non-matching parameters

I have the following unit test verification using Moq:
var mock = new Mock<IDoSomethingUseful>();
var sut = new Thingy(mock.Object);
sut.CallDoSomethingUseful();
mock.Verify(
somethingUseful => somethingUseful.Move(
It.Is<MyVector>(
myVector => myVector.x == 123)), Times.Once, "This fail message needs to be hard-coded with myVector.x was not equal to 123");
How can I get Verify() to tell me that the predicate match failed? The test runner only reports that the call failed so I need to rely on the hard-coded message.
Using Callback the invocation arguments can be accessed. See section Callbacks here.
In your case you could add an expected value for x to the test and get the actual value in Callback. Finally use an Assert to verify if expected and actual values equal where the message can be formated using both values. HTH
int expected_x_value = 123;
int actual_x_value = 0;
var mock = new Mock<IDoSomethingUseful>();
mock.Setup(m => m.Move(It.IsAny<MyVector>()))
.Callback<MyVector>(
(v) =>
{
actual_x_value = v.x;
}
);
var sut = new Thingy(mock.Object);
sut.CallDoSomethingUseful();
Assert.AreEqual(expected_x_value, actual_x_value,
string.Format("myVector.x was expected to be called with x = '{0}' but was '{1}'",
expected_x_value, actual_x_value));

How should I Parse and Delay a Hot Reactive Extensions IConnectableObservable<T> stream?

I am unable to implement this, so unfortunately I have no Rx code to show where I am at. I will explain what i would like t do, and hopefully someone out there with enough expertise might be able to guide me in the right direction.
Let us say that I have a collection of List TimeObjects that I pulled from a database. TimeObject has this form.
public class TimeObject
{
public DateTime time{get;set;}
public decimal price{get;set;}
}
What I want to do is produce a Hot IConnectableObservable stream, where each element is separated by a variable time delay.
The variable time delay is equal to the difference between the time of the current and the next TimeObject.
For example, if the stream is this:
s1, s2, s3, ...sN, where each 's' represents an element of TimeObject
Then, the time delay before s2 is pushed out to the stream is (s2.time - s1.time),
the time delay before s3 is pushed out to the stream is (s3.time - s2.time) and so on.
Is this at all possible, and if so, what should my implementation look like?
I have included a for loop that accomplishes the same task using a classical approach.
FireEvent(TimeObject[0]); //Post the first element as an event
for(int _counter = 0; _counter < TimeObject.Count; _counter++)
{
if ( _counter + 1 < TimeObject.Count )
{
TimeObject timeObjectA = TimeObject[_counter];
TimeObject timeObjectB = TimeObject[_counter + 1];
int millisecondsDelay = (timeObjectB.time - timeObjectA.time).Milliseconds;
Thread.Sleep(millisecondsDelay);
FireEvent(timeObjectB); //this posts the latest tick as an event with variable time delay.
}
What I would like is for this to be converted into an Observable stream.
Thanks.
Try this:
var observable =
Observable
.Generate(
1,
x => x < timeObjects.Count,
x => x + 1, x => timeObjects[x],
x => timeObjects[x].time.Subtract(timeObjects[x - 1].time)))
.StartWith(timeObjects[0]);
Now, this is a regular cold observable. You could make it hot by calling .Publish(). Why do you need it hot?
It also requires your list to have at least two elements

global variable not getting set with proper values in another function in flex

I have a global variable 'csId' of string type. In the code below under drawChart() function, in for loop, csID variable should be set to '1' by the modelLocator when i=0 and csId should be set to '2' by modelLocator when i=1.(considering lengh=2).
Alert in drawchart() (for csId) seems to be printing the right 'csid' values(both 1 and 2) but in the dataFunction() 'columnSeries_labelFunc' i am always getting the csId Alert value as '2' and never as '1'.
Please find the code below:
drawchart() function::
public function drawChart():void
{
var cs:ColumnSeries= new ColumnSeries();
var lenght:Number=AppModelLocator.getInstance().ctsModel.productSummary.getItemAt(0).collMgmtOfcList.length;
myChart.series = [cs];
var tempObj:Object;
for(csLoop=0;csLoop<lenght;csLoop++)
{
cs = new ColumnSeries();
this.csId= new String(String(AppModelLocator.getInstance().ctsModel.productSummary.getItemAt(0).collMgmtOfcList[csLoop]));
Alert.show("csId="+this.csId);
cs.id=this.csId;
cs.displayName = 'Exposure';
cs.dataFunction=columnSeries_labelFunc;
myChart.series[csLoop] = cs;
}
columnSeries_labelFunc() function::
private function columnSeries_labelFunc(series:Series, item:Object, fieldName:String):Object {
var col:Number=0;
Alert.show("value of csid in columnSeries_labelFunc="+this.csId);
if(fieldName == "yValue" && series.id==csId){
return(item.exposureUSDList[0]);
}else if(fieldName == "yValue" && series.id==csId) {
return(item.exposureUSDList[1]);
}else if(fieldName == "xValue"){
return(item.rptType);
}else
return null;
}
Please Help!!!
First: Assigning a value to a global variable repeatedly inside a loop is a bad idea. Nothing good will happen from that.
It's hard to tell from the context here, but the most likely reason that you're having this problem is that the flow of execution is as follows:
drawChart() executes synchronously, counting through each step in the loop, creating the ColumnSeries, which are each invalidated, meaning they will redraw on the next frame. The function ends, with csID at the last value it held.
The app goes into the next step in the elastic racetrack and validates the invalidated components.
columnSeries_labelFunc is called, with csID still holding the terminal value from the loop.
The end result being that columnSeries_labelFunc isn't called until you're already completely finished in drawChart.
The simplest fix would be to read the id that you're setting on the series in the label function, rather than relying on a global variable at all.

Resources