I have an ILogger interface with LogTrace(string value, params object[] parameters). Now I want to verify that the LogTrace is called and the string to log contains some id. The problem is that it can be called differently. E.g. 1) LogTrace("MyString " + id) 2) LogTrace("MyString {0}", id) and so on.
Is there a good way with Moq to verify all the scenarios? I can only think of creating a hand-made mock that will format the string that will be available for verification.
When you need to verify that the code under test called a method with the expected parameters, you can mock the method with Moq and use Verify() + It.Is<T>() to check the parameters passed in. Verify() asserts that the method call happened as expected with the specified parameters.
mock. Verify(p => p. Send(It. IsAny<string>())); The Verify method offers additional overloads to specify the fail message and the amount of times the invocation was expected to be performed.
You can use Moq to create mock objects that simulate or mimic a real object. Moq can be used to mock both classes and interfaces.
Callbacks. A powerful capability of Moq is to attach custom code to configured methods and properties' getters and setters. This capability is often referred to as Callbacks.
mock.Verify( m => m.LogTrace( It.IsAny<string>(), It.IsAny<object[]>() ) );
The params object[]
is passed to the method as object[]
anyway so you just have to match the array somehow (as above for example, this accepts anything).
If you need more control over the list, use the It.Is
matcher which allows you to create your own predicate:
mock.Verify( m => m.LogTrace( It.IsAny<string>(),
It.Is<object[]>(ps =>
ps != null &&
ps.Length == 1 &&
ps[0] is int &&
(int)ps[0] == 5
) ) );
This example shows how to verify if the param list is not empty and contains 5
as the only parameter of type int
.
I don't think there is an easy way for doing what you need here. The problem is that you need to ensure that a certain combination of values will be passed to your method, which results in many different verifiable scenarios:
However, Moq does not support this sort of conditional expressions between different arguments of your verifiable method. One possible solution is to check for the absence of an id, instead of its presence in either argument. Try something like:
mock.Verify(m => m.LogTrace(
It.Is<string>(s => !s.Contains(id)),
It.Is<object[]>(o => !o.Contains(id))), Times.Never());
What we are doing here is verifying whether the fail condition is ever met - that is, your string does not contain an id, and neither does your object array. We use Times.Never() to make sure that this situation should never happen.
Keep in mind, however, that the code might not be obvious at first glance; make sure you properly explain your intent once you write it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With