Replies: 2 comments
-
Hi, I want to bring up the question. I also have the same problem. I need to make mocks to substitute values in tests, but at the moment this cannot be achieved because For example, I want to check the correctness of calling metrics inside my code: private const long Capacity = 20;
private const long ConsumeBuckets = 5;
private Counter<long> _throwingCounter;
[TestInitialize]
public void Init()
{
_throwingCounter = Substitute.For<Counter<long>>("name"); // We can't do it
_throwingCounter.When(fake => fake.Add(ConsumeBuckets))
.Do(_ => throw new Exception());
}
[TestMethod]
public void ExceptionSwallowed_Success()
{
var spins = Capacity * 3;
var expectedCatches = spins - Capacity; // We should be able to consume cap and then throttle
long consumeRate = 1;
var bucket = TokenBucketBuilderFactory.Create()
.WithCapacity(Capacity)
.WithTimeSpanRefillStrategy(() => new TimeSpanRefillStrategy(20, TimeSpan.FromSeconds(20)))
.WithThrottledTokensCounter(() => _throwingCounter)
.Build();
for (var i = 0; i < spins; i++)
{
bucket.TryConsume(consumeRate); // Change _throwingCounter inside
}
_throwingCounter.Received((int)expectedCatches).Add(consumeRate);
} If there is an issue or other discussion, please share. |
Beta Was this translation helpful? Give feedback.
-
It has been a while since the question was asked, but in case anyone stumbles on this, the easiest way to test |
Beta Was this translation helpful? Give feedback.
-
I've started using the
System.Diagnostics.Metrics.Counter<T>
class in my code to keep track of some custom metrics that will be published to Azure and used as a mechanism for business notifications.While creating my solution, I quickly realized how test unfriendly most of the involved classes are.
In particular:
Counter<T>
defines variousAdd
methods but those are not part of any abstraction that can be mocked. If I try to mockInstrument<T>
instead, then it also doesn't work since that doesn't expose any public abstractions that can actually be called by my implementation.Meter
also has no abstractions behind it, so instantiating one creates a "real" metric that is only capable of creating "real" instruments. This is also not fit for unit testingMeterListener
is callback-based, meaning it is very hard to adapt it to use in an integration test scenario. One would be forced to use a manual reset event or something similar to "wait" for some measurements to be able to make assertions about the code in a sequential manner. For example, "check that a measurement was made when calling method X on my class".For now, I'll probably need to create my own
ICounter<T>
abstraction with an accompanying adapter implementation to wrap the standardCounter<T>
so I can do some basic assertions on the injected counter instances during an unit test, but this feels less than ideal, especially becauseCounter<T>
has several overloads that all semantically "do the same thing", so I'd need to expose those in my own abstraction in some form and this would result in a lot of duplicated code.What is the current recommended approach for testing (both unit and integration) code that relies on
Instrument<T>
?Beta Was this translation helpful? Give feedback.
All reactions