Skip to content
New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corrected Verify method behavior for generic methods calls #25

Merged
merged 3 commits into from
Sep 21, 2012
Merged

Corrected Verify method behavior for generic methods calls #25

merged 3 commits into from
Sep 21, 2012

Conversation

Suremaker
Copy link

Hello,

I have corrected the code in Moq to support counting of generic method calls for parameter represented by base class / interface like in example below:

public interface IBaz
{
void Call(T param) where T:IBazParam;
}
public void MatchesDerivedTypesForGenericTypes()
{
var mock = new Mock();
mock.Object.Call(new BazParam());
mock.Object.Call(new BazParam2());
mock.Verify(foo => foo.Call(It.IsAny()), Times.Exactly(2));
}

wojtek added 2 commits August 6, 2012 17:40
public interface IBaz
{
	void Call<T>(T param) where T:IBazParam;
}
public void MatchesDerivedTypesForGenericTypes()
{
	var mock = new Mock<IBaz>();
	mock.Object.Call(new BazParam());
	mock.Object.Call(new BazParam2());
	mock.Verify(foo => foo.Call(It.IsAny<IBazParam>()), Times.Exactly(2));
}
@Suremaker
Copy link
Author

Hello,

I would like to describe problem solved by this fix.
Below is an example of message handling classes:

  • IMessageHandler interface is for handling messages of any type implementing IMessage interface
  • MyMessage and OtherMessage implement it.

The tests shows two cases that may happen in code:

  1. Calling Handle < MyMessage > () and Handle < OtherMessage > () by passing messages by classes type
  2. Calling Handle < IMessage > () twice by passing messages by interface type

For both situations I would like to test that two IMessage objects has been handled and they were MyMessage and OtherMessage.

With current Moq implementation is it not possible to make test 1. pass:
Expected invocation on the mock exactly 2 times, but was 0 times: h => h.Handle < IMessage > (It.IsAny < IMessage > ())

Test 2. is possible to write by specifying that we are checking Handle < IMessage > () method calls (CountingMessagesSendAsInterface_Workaround shows that).

My fix allows to make 1. test passing by making Moq counting the calls of the generic method with parameter type that derives from given one.
Having that, the Handle < MyMessage > () and Handle < OtherMessage > () is being taken into account during count of Handle < IMessage > () calls.
Unfortunatelly my fix does not making test 2. passing but it is possible to have a workaround for it.

Thanks,
Wojtek

public interface IMessage { }
public class MyMessage : IMessage { }
public class OtherMessage : IMessage { }
public interface IMessageHandler
{
    void Handle<TMessage>(TMessage message)
        where TMessage : IMessage;
}

[TestFixture]
public class Tests
{
    [Test]
    public void CountingMessagesSendAsClass()
    {
        var messageHandler = new Mock<IMessageHandler>();
        messageHandler.Object.Handle(new MyMessage());
        messageHandler.Object.Handle(new OtherMessage());

        messageHandler.Verify(h => h.Handle(It.IsAny<IMessage>()), Times.Exactly(2));
        messageHandler.Verify(h => h.Handle(It.IsAny<MyMessage>()), Times.Once());
        messageHandler.Verify(h => h.Handle(It.IsAny<OtherMessage>()), Times.Once());
    }

    [Test]
    public void CountingMessagesSendAsInterface()
    {
        var messageHandler = new Mock<IMessageHandler>();
        IMessage message1 = new MyMessage();
        IMessage message2 = new OtherMessage();
        messageHandler.Object.Handle(message1);
        messageHandler.Object.Handle(message2);

        messageHandler.Verify(h => h.Handle(It.IsAny<IMessage>()), Times.Exactly(2));
        messageHandler.Verify(h => h.Handle(It.IsAny<MyMessage>()), Times.Once());
        messageHandler.Verify(h => h.Handle(It.IsAny<OtherMessage>()), Times.Once());
    }

    [Test]
    public void CountingMessagesSendAsInterface_Workaround()
    {
        var messageHandler = new Mock<IMessageHandler>();
        IMessage message1 = new MyMessage();
        IMessage message2 = new OtherMessage();
        messageHandler.Object.Handle(message1);
        messageHandler.Object.Handle(message2);

        messageHandler.Verify(h => h.Handle(It.IsAny<IMessage>()), Times.Exactly(2));
        messageHandler.Verify(h => h.Handle<IMessage>(It.IsAny<MyMessage>()), Times.Once());
        messageHandler.Verify(h => h.Handle<IMessage>(It.IsAny<OtherMessage>()), Times.Once());
    }
}

@Suremaker
Copy link
Author

Hello,

I corrected the typo. Thank you for pointing it :)

I am looking forward to be able to download Moq with this fix from NuGet.

Thank you,
Wojtek

kzu added a commit that referenced this pull request Sep 21, 2012
Corrected Verify method behavior for generic methods calls
@kzu kzu merged commit 9db9822 into devlooped:dev Sep 21, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants