This is a migrated thread and some comments may be shown as answers.

Accessing future instances in DoInstead expressions

3 Answers 99 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Bob
Top achievements
Rank 1
Bob asked on 17 Nov 2013, 01:54 PM
Hello Telerik Team,

I am working with JustMock and I need to Mock a method that creates 5 instances of PerformanceCounters (MSFT object).  My method under test then performs calculations and sets each of these 5 counters with various values.  I need to check and Assert on these values in my Unit Test.

However, since these 5 objects get created inside my method under test (and I cannot change that code), I am wondering how to get access to these instances during my JustMock test. Specifically, I need to capture the RawValue property (both get and set) to make sure that the right values are sent into and returned from the property.  Without any access to the actual instances, I can;t see how this is done.

As a point of reference, Microsoft Fakes has a technique that specifies 'AllInstances' and this passes in the current object as one of the parameters  (see below, the 'counter' parameter)

                ShimPerformanceCounter.AllInstances.IncrementByInt64 =
                    (counter, l) => ShimsContext.ExecuteWithoutShims(() => counter.IncrementBy(l));

Any ideas ?

3 Answers, 1 is accepted

Sort by
0
Kaloyan
Telerik team
answered on 18 Nov 2013, 11:42 AM
Hello Bob,

Thank you for contacting our support central.

To achieve this, you will need to use Future Mocking.

I have prepared a simple example in order to guide you further. Assume we have the next TestClass:
public class TestClass
{
    public long TestMethod()
    {
        var performanceCounters = new PerformanceCounter();
 
        return performanceCounters.RawValue;
    }
}

Now, to mock the return value of the RawValue property, we can use the following:
[TestMethod]
public void TestMethod1()
{
    long expected = 123;
 
    // Arrange
    var perf = new PerformanceCounter();
 
    Mock.Arrange(() => perf.RawValue).IgnoreInstance().Returns(expected);
 
    // Act
    var testClass = new TestClass();
    var actual = testClass.TestMethod();
 
    // Assert
    Assert.AreEqual(expected, actual);
}

The above test arranges that any instance of the PerformanceCounter class should return expected value for its RawValue property getter.

I hope this helps. Let me know if I can assist you with anything else.

Regards,
Kaloyan
Telerik
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Bob
Top achievements
Rank 1
answered on 18 Nov 2013, 01:56 PM
Hello again,

Thanks for that answer but it is not quite what I was asking.  Here is what I have (basically).
The actual code actually performs some quite complex calculations and updates many counters in the method.
Mocking the GET property is actually not what I need.  In fact, that's the whole point of the test!! I need to make sure the
performance counters have been properly updated to the correct values.  So my Unit Test actually calls into 'TestMethod' with various scenarios and then 'reads' the performance counters to make sure they got set with the right values. (The performance counters do *NOT* interact with the Operating system and this is very isolated.

** If I use future mocking and override the GET property of PerformanceCounter,
how do I know which counter is currently being referenced?? As you can see, I need to differentiate between the 'real' counter and the TOTAL counter.  In other words, where is the actual instance ?



public class TestClass
{
    
public Dictionary<string, PerformanceCounter> _counters =
                   
new Dictionary<string, PerformanceCounter>();

    
public long TestMethod(string counterName, long failureCount)
    {
        PerformanceCounter instanceCounter =
null;
        PerformanceCounter totalCounter =
null;

        
if (!_counters.TryGetValue(counterName, out instanceCounter))
        {
            instanceCounter =
new PerformanceCounter();
            _counters.Add(counterName, performanceCounter);
        }
        
if (!_counters.TryGetValue("TOTAL", out totalCounter))
        {
            totalCounter =
new PerformanceCounter();
            _counters.Add(
"TOTAL", totalCounter);
        }
        instanceCounter.RawValue = failureCount;
        totalCounter.RawValue += failureCount;

        
return instanceCounter.RawValue;
    }
}

0
Kaloyan
Telerik team
answered on 20 Nov 2013, 01:02 PM
Hello Bob,

Thank you for clarifying this.

To make sure that the performance counters have been updated properly, you can expect a certain property set to occur exact number of times.

As I am not aware of the actual system under test, I made the following:
    public void PCCalculations()
    {
        if(!PerformanceCounterCategory.Exists("CategoryName1"))
            PerformanceCounterCategory.Create("CategoryName1", "CounterHelp1",
                PerformanceCounterCategoryType.SingleInstance,
                "CounterName1", "CounterHelp1");
 
        var performanceCounter1 = new PerformanceCounter("CategoryName1", "CounterName1", false);
        performanceCounter1.RawValue = 1;
        // some calculations ...
        long raw1 = performanceCounter1.RawValue;
 
        if (!PerformanceCounterCategory.Exists("CategoryName2"))
            PerformanceCounterCategory.Create("CategoryName2", "CounterHelp2",
                PerformanceCounterCategoryType.SingleInstance,
                "CounterName2", "CounterHelp2");
 
        var performanceCounter2 = new PerformanceCounter("CategoryName2", "CounterName2", false);
        performanceCounter2.RawValue = 2;
        // some calculations ...
        long raw2 = performanceCounter2.RawValue;
    }
}
Basically, it creates two performance counters and updates their RawValue property.

Now, to check if the RawValue property has been set accordingly in the test execution, you can use the following:
[TestMethod]
public void TestMethod1()
{
    // Arrange
    var perf = Mock.Create<PerformanceCounter>();
 
    Mock.ArrangeSet(() => perf.RawValue = 1).IgnoreInstance().CallOriginal().OccursOnce();
    Mock.ArrangeSet(() => perf.RawValue = 2).IgnoreInstance().CallOriginal().Occurs(1);
 
    // Act
    var testClass = new TestClass();
    testClass.PCCalculations();
    var performanceCounter1 = new PerformanceCounter("CategoryName1", "CounterName1", false);
    var performanceCounter2 = new PerformanceCounter("CategoryName2", "CounterName2", false);
 
    // Assert
    Mock.Assert(perf);
    Assert.AreEqual(1, performanceCounter1.RawValue);
    Assert.AreEqual(2, performanceCounter2.RawValue);
}
In the test, I arrange that RawValue should be set to 1, no matter its instance. In the same time this set should execute the original setter logic and it should occur exactly once. If the arrangements expect equal arguments for the setter, you can update the occurrences accordingly (use a single arrange for all the equal values setters and expect the exact number of occurrence - e.g., Mock.ArrangeSet(() => perf.RawValue = 2).IgnoreInstance().CallOriginal().Occurs(3);). More about these features can be found here: IgnoreInstance, CallOriginal, Asserting Occurrences

After being sure that the RawValue properties have been set as expected, I am checking if the calculations inside the method under test are correct. For this I create new PerformanceCounters in the test and assert against their RawValues.

If this does not apply to your scenario, I will require a sample project, reproducing the matter. Then, I will be able to assist you with the correct approach.

I hope this helps.

Regards,
Kaloyan
Telerik
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
Tags
General Discussions
Asked by
Bob
Top achievements
Rank 1
Answers by
Kaloyan
Telerik team
Bob
Top achievements
Rank 1
Share this question
or