Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Provide better error reporting in Verify() #84

Open
ashmind opened this Issue Jan 16, 2014 · 2 comments

Comments

Projects
None yet
3 participants
Contributor

ashmind commented Jan 16, 2014

Example of reporting I get in 4.1.1311.615:

Moq.MockException : 
Expected invocation on the mock at least once, but was never performed:
r => r.Save(It.Is<Entity>(e => e.Description == .expectedDescription))
No setups configured.

Performed invocations:
IRepository`2.Save(My.Entity)

Reporting that would be more useful:

Moq.MockException : 
Expected invocation on the mock at least once, but was never performed:
r => r.Save(It.Is<Entity>(e => e.Description == "ABC"))
No setups configured.

Performed invocations:
IRepository`2.Save(My.Entity { Description = "XYZ" })

As for the second point, I have done similar thing once -- can be done by finding all distinct property/method paths in expression tree passed to It.Is and requesting their values for actual argument.

icalvo commented Nov 5, 2015

I think that for objects you have a nice workaround most of the times, which is to override ToString(). But if you do not have control over the class, this would be nice to have. You have to take into account the possible length of the resulting string, and also circular references if you recursively print property values. Not trivial at all!

Also interesting for enhancing reporting is when you have array parameters, which is specially useful for params methods. Also in-memory collections such as Dictionary, List and Collection. I'd not recommend to implement it for IEnumerable or other interfaces because you could have a huge (or even infinite) sequence there. The same caveats about the length of the resulting string and circular references apply.

Member

stakx commented Jun 12, 2017 edited

I think this idea has a lot of potential. But I don't think it would be good to decide on one fixed way of reporting additional object data, because of the problems this could cause (see @icalvo's post above).

I would suggest that this new functionality be exposed in a slightly more general way. For example, a new public contract could be introduced, say:

namespace Moq.Diagnostics
{
    public interface IObjectFormatter
    {
        string Format(object obj);
    }
}

Exactly one instance of this new interface type could then be registered on a Mock or MockRepository. This would then be used in messages to (you guessed it) create a string representing a specific object. Such a string could consist only of the type name, but it could also include the property names and values of an object, or the first n items of a sequence, etc.

By default, Moq would be using a DefaultObjectFormatter implementation that produces the exact same output as Moq does today.

If the questions raised in the post above can be solved such that the resulting formatting would work well for most objects, Moq could ship with one (or several) additional concrete implementations in the new Moq.Diagnostics namespace that people could use to quickly switch over to more advanced error reporting.

@stakx stakx added the enhancement label Jun 12, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment